SpringAop
作用
在不修改原来代码的前提下,实现对代码的增强功能;
比如:使用 aop 实现日志:https://www.cnblogs.com/Jomini/p/13218872.html
使用:https://www.cnblogs.com/liantdev/p/10125284.html
Join point 连接点
连接点是程序执行的一个点.。一个方法的执行或者一个异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。举例来说,所有定义在你的 EmpoyeeManager接口中的方法都可以被认为是一个连接点
Pointcut 切点
一个方法的执行或者一个异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。举例来说,所有定义在你的 EmpoyeeManager接口中的方法都可以被认为是一个连接点
//匹配com.aop.service.impl.ProductServiceImpl类下方法名以select或delete开头的所有方法
@Pointcut("execution(* com.aop.service.impl.ProductServiceImpl.select*(..)) || " +
"execution(* com.aop.service.impl.ProductServiceImpl.delete*(..))")
public void matchCondition() {}
//使用matchCondition这个切入点进行增强
@Before("matchCondition()")
public void before() {
System.out.println("before 前置通知......");
authService.checkAccess();
}
Advice
通知是指拦截到Joinpoint之后所要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知和环绕通知(切面要完成的功能)
1.@Before前置通知
前置通知在切入点运行前执行,不会影响切入点的逻辑
2.@After后置通知
后置通知在切入点正常运行结束后执行,如果切入点抛出异常,则在抛出异常前执行
3.@AfterThrowing异常通知
异常通知在切入点抛出异常前执行,如果切入点正常运行(未抛出异常),则不执行
4.@AfterReturning返回通知
返回通知在切入点正常运行结束后执行,如果切入点抛出异常,则不执行
5.@Around环绕通知
环绕通知是功能最强大的通知,可以在切入点执行前后自定义一些操作。环绕通知需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行
//匹配com.aop.service.impl.ProductServiceImpl类下面的所有方法
@Pointcut("execution(* com.aop.service.impl.ProductServiceImpl.*(..))")
public void matchAll() {}
@Around("matchAll()")
public Object around(ProceedingJoinPoint joinPoint) {
Object result = null;
authService.checkAccess();
System.out.println("befor 在切入点执行前运行");
try{
result = joinPoint.proceed(joinPoint.getArgs());//获取参数
System.out.println("after 在切入点执行后运行,result = " + result);
} catch (Throwable e) {
System.out.println("after 在切入点执行后抛出exception运行");
e.printStackTrace();
} finally {
System.out.println("finally......");
}
return result;
}
Aspect
Aspect切面表示Pointcut(切入点)和Advice(增强/通知)的结合
Spring Aop中四个重要概念,切点,切面,连接点,通知 关系
1. 通知: 就是我们编写的希望Aop时执行的那个方法。我们通过Aop希望我们编写的方法在目标方法执行前执行,或者执行后执行。
2. 切点:切点就是我们配置的满足我们条件的目标方法。比如我们规定:名字前面是select开头的才执行我们自定义的通知方法。那么这些select开头的方法就是切点。
3. 连接点:连接点可以说是切点的全集。切点是连接点的子集。也可以理解为,连接点是我们没有定义那个select开头规则时,满足条件的全部的方法。
4. 切面:切面是切点和通知的组合称谓,就是变相给组合起了个名字。
实现原理
使用 Cglib 和 动态代理 实现
Cglib 对比 动态代理
Cglib 底层使用 ASM 框架,来操作字节码生成新的类
动态代理 只能对接口代理,没有接口就不能实现
动态代理提供 Proxy 类来创建代理,Cglib 提供 Enhancer 来创建代理
参考:https://www.cnblogs.com/Jomini/p/13272571.html
使用方式
aspect 切面
Point cut (如果理解了这个切点的概念,就在应用方面完全是可以的了)表示连接点的集合(类似一个表)
Join point 目标对象中的方法(每一条记录)
weaving 把代理逻辑加入到目标对象上的过程叫做织入
advice 通知类型,请下下图官网说明
面试:
问:
是编译时期进行织入,还是运行期进行织入?
答:
运行期,生成字节码,再加载到虚拟机中,JDK是利用反射原理,CGLIB使用了ASM原理。
问:
初始化时期织入还是获取对象时织入?
答:
初始化的时候,已经将目标对象进行代理,放入到spring 容器中
源码分析: