目录
1.AOP概念理解
软件开发中散布于应用中多处的功能被称为横切关注点,把这些横切关注点与业务逻辑分离,正是面向切面编程所要关注的问题,AOP是一种编程的范式,类似于面向过程,面向函数编程,面向对象编程一样。另外他解决的是特定的问题而不是所有的问题。
Spring AOP 构建在动态代理的基础上,因此Spring 对 AOP的支持局限于方法拦截,如果需要方法拦截之外的连接点的拦截功能,那么我们可以利用AspectJ来补充Spring AOP的功能。
AOP相关注解
@EnableAspectJAutoProxy
@Aspect
@PointCut
@Before、@Around、@After
@AfterReturning
@AfterThrowing
AOP的初衷是什么?第一个初衷就是消除重复的代码。第二个初衷是将关注点分离:
使用AOP的好处:
AOP的使用场景:
横切关注点被模块化为特殊的类,这个类就被称为切面。
通知定义了切面是什么以及何时使用,通知包含了需要应用于多个应用对象的横切行为。
连接点是在应用执行过程中能够插入切面的一个点。,是程序执行过程中能够应用通知的所有点。
切点的定义会匹配通知所要织人的一个或多个连接点。切点定义了通知被应用的具体位置。
织入是把切面应用到目标对象并创建新的代理对象的过程。
最关键的概念就是切点定义了哪些连接点会得到通知。创建切点来定义切面所织入的连接点是AOP框架的基本功能。
2.切点表达式的构成
切面表达式,切点表达式中主要包含三个部分:通配符,运算符,指示器。
重点是execution()
匹配包:
匹配对象:第三个是根据bean的id来匹配的
参数匹配:
注解匹配:
只想拦截抛出异常的方法
3.Spring AOP实例:
先要找到应用中的连接点,即需要通知的点。
编写切面和切点表达式:
@Aspect
public class Audience {
//定义命名的切点
@Pointcut("execution(* *com.wx.springinaction.service.Performance.perform(..))")
public void performance() {
}
@Before("performance()")
public void silenceCellPhone() {
System.out.println("看表演之前,观众将收集调成静音");
}
@Before("performance()")
public void takeSeats() {
System.out.println("观众入席坐好");
}
// @After 和 @AfterReturning区别:@After=@AfterReturning+@AfterThrowing
@AfterReturning("performance()")
public void applause() {
System.out.println("演出结束观众鼓掌");
}
@AfterThrowing("performance()")
public void demandRefund() {
System.out.println("演出失败,观众要求退款!!!");
}
}
注入切面的bean
@Configuration
@EnableAspectJAutoProxy //启动AspectJ自动代理
@ComponentScan("com.wx.springinaction.service")
public class PerformanceConfig {
@Bean
public Audience audience() {
return new Audience();
}
}
测试:
下面继续展示环绕通知的用法:
@Around("performance()")
public void around(ProceedingJoinPoint proceedingJoinPoint){
try {
System.out.println("看表演之前,观众将收集调成静音");
System.out.println("观众入席坐好");
proceedingJoinPoint.proceed();
System.out.println("演出结束观众鼓掌 !!");
}catch (Throwable e){
System.out.println("演出失败,观众要求退款!!!");
}
}
下面继续展示处理通知中的参数:
连接点变成:
切点变成:
切面变成:
测试:
继续演示通过注解引入新的功能,如果一个切面能够为一个方法增加新的功能,为什么能为一个对象增加新的功能呢?利用引入的AOP概念,切面可以为Spring Bean增加新的方法。特别是没有源码控制权的时候。
要引入表演类的新方法:
新写一个切面:加号表示接口下的所有实现。以及引入接口方法的
配置注入Bean
使用
结果:
Spring AOP的演示到此为止,如果要更加强大的AOP,支持更多的类型那就需要AspectJ,例如当我们创建对象时候可以增加构造器通知,对象属性的改变也可以通知等等众多的类型。
4.Spring AOP的原理:
用到的设计模式两种:代理模式,责任链模式,动态代理。
首先是织入的时机,对于Spring来讲,AOP织入的时机是运行期。
代理:
动态代理:java基础--19动态代理
代理的方式有两种,JDK和CGLib,那么Spring AOP 选择的是什么代理方式呢?
Spring 是如何创建出代理的bean呢?
如何强制使用CGlib的代理:
然后我们再回答一个问题,多个AOP调用时如何叠加在一起的,答案是采用了责任链的模式
在Spring 启动的时候,运行期,Spring就会扫描到带有@Aspect注解的切面类,然后根据切点的表达式匹配出所有的连接点,然后会判断这个目标对象是接口实现还是继承实现,然后就可以确定使用JDK还是CGLib的代理方式生成代理类。顺便会判断通知的类型,最后调用的时候当然就是调用代理类啦。