能够理解AOP的作用
能够完成AOP的入门案例
能够理解AOP的工作流程
能够说出AOP的五种通知类型
能够完成"测量业务层接口万次执行效率"案例
能够掌握Spring事务配置
问题1:AOP的作用是什么?
问题2:连接点和切入点有什么区别,二者谁的范围大?
问题3:请描述什么是切面?
AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构
作用:在不惊动原始设计的基础上为其进行功能增强。简单的说就是在不改变方法源代码的基础上对方法进行功能增强。
Spring理念:无入侵式/无侵入式
连接点(JoinPoint):正在执行的方法,例如:update()、delete()、select()等都是连接点。
切入点(Pointcut):进行功能增强了的方法,例如:update()、delete()方法,select()方法没有被增强所以不是切入点,但是是连接点。
在SpringAOP中,一个切入点可以只描述一个具体方法,也可以匹配多个方法
通知(Advice):在切入点前后执行的操作,也就是增强的共性功能
通知类:通知方法所在的类叫做通知类
切面(Aspect):描述通知与切入点的对应关系,也就是哪些通知方法对应哪些切入点方法。
问题1:在通知方法中如何定义切入点表达式?
问题2:如何配置切面?
问题3:在配置类上如何开启AOP注解功能?
案例设定:测定接口执行效率
简化设定:在接口执行前输出当前系统时间
开发模式:XML or ==注解==
思路分析:
<dependencies>
<!--spring核心依赖,会将spring-aop传递进来-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!--切入点表达式依赖,目的是找到切入点方法,也就是找到要增强的方法-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
x
public interface BookDao {
public void save();
public void update();
}
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println(System.currentTimeMillis());
System.out.println("book dao save ...");
}
public void update(){
System.out.println("book dao update ...");
}
}
xxxxxxxxxx
//通知类必须配置成Spring管理的bean
public class MyAdvice {
public void method(){
System.out.println(System.currentTimeMillis());
}
}
xxxxxxxxxx
//通知类必须配置成Spring管理的bean
//设置当前类为切面类类
public class MyAdvice {
//设置切入点,@Pointcut注解要求配置在方法上方
"execution(void com.itheima.dao.BookDao.update())") (
private void pt(){}
//设置在切入点pt()的前面运行当前操作(前置通知)
"pt()") (
public void method(){
System.out.println(System.currentTimeMillis());
}
}
xxxxxxxxxx
"com.itheima") (
//开启注解开发AOP功能
public class SpringConfig {
}
xxxxxxxxxx
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
bookDao.update();
}
}
什么是目标对象?什么是代理对象?
Spring容器启动
读取所有切面配置中的切入点
初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
获取bean执行方法
目标对象(Target):被代理的对象,也叫原始对象,该对象中的方法没有任何功能增强。 代理对象(Proxy):代理后生成的对象,由Spring帮我们创建代理对象。
xxxxxxxxxx
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
BookDao bookDao = ctx.getBean(BookDao.class);
bookDao.update();
//打印对象的类名
System.out.println(bookDao.getClass());
}
}
在切入点表达式中如何简化包名和参数类型书写?
切入点:要进行增强的方法
切入点表达式:要进行增强的方法的描述方式
xxxxxxxxxx
execution(void com.itheima.dao.BookDao.update())
xxxxxxxxxx
execution(void com.itheima.dao.impl.BookDaoImpl.update())
切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数) 异常名)
xxxxxxxxxx
execution(public User com.itheima.service.UserService.findById(int))
目的:可以使用通配符描述切入点,快速描述。
匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法
xxxxxxxxxx
execution(public * com.itheima.*.UserService.find*(*))
匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法
xxxxxxxxxx
execution(public User com..UserService.findById(..))
xxxxxxxxxx
execution(* *..*Service+.*(..))
请描述一下如何定义环绕通知方法?
AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码时要将其加入到合理的位置
AOP通知共分为5种类型
xxxxxxxxxx
"pt()") (
public void before() {
System.out.println("before advice ...");
}
xxxxxxxxxx
"pt()") (
public void after() {
System.out.println("after advice ...");
}
xxxxxxxxxx
"pt()") (
public void afterReturning() {
System.out.println("afterReturning advice ...");
}
xxxxxxxxxx
"pt()") (
public void afterThrowing() {
System.out.println("afterThrowing advice ...");
}
xxxxxxxxxx
"pt()") (
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice ...");
Object ret = pjp.proceed();
System.out.println("around after advice ...");
return ret;
}
==环绕通知注意事项==