1、AOP解决了什么问题?
低侵入性扩展已有程序逻辑。
2、几个核心概念
连接点(Joinpoint):用方法表示的程序执行点的前后执行位置就是连接点,也即:一个方法的执行前、执行后的某个位置或时机,执行前或后又叫做方位。Spring使用切点对执行点进行定位,在增强(Advice)中定义方位。
切点(Pointcut):执行点的查询筛选定位规则,按规则筛选后的执行点通常是某个方法。
增强(Advice):增强定义了:织入目标类连接点上的一段程序代码和执行点方位信息。附加于连接点的增强逻辑、增强动作,本质:一段执行逻辑。额外包含增强的方位信息,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice等。增强类型(增强逻辑+切入方位):Before(前置增强)、After/AfterReturning(后置增强)、Around(环绕增强)、AfterThrowing(异常抛出增强);切点加增强才能确定特定连接点和并织入增强逻辑。
目标对象(Target):增强逻辑织入的目标对象。
织入(Weaving):织入是将增强逻辑嵌入到目标类的具体连接点上的过程。
AOP有3种织入方式:
编译期织入,需要使用特殊的编译器;
类装载期织入,需要使用特殊的类装载器;
动态代理织入,在运行期为目标类添加增强生成子类的方式。
Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。
代理(Proxy):一个类被AOP织入增强后生成的结果类,该结果类是融合了原类和增强逻辑的代理类。
切面(Advisor/Aspect):切点和增强逻辑的定义类。
引介(Introduction):动态的为业务类添加接口的实现逻辑,让该类成为这个接口的实现类。
3、增强织入的顺序
一个连接点可织入多个增强,它们的织入顺序可按如下规则判断:
同一个切面类中声明的增强:按定义顺序自上往下进行织入;
不同切面类中声明的增强:若所有切面类都实现了org.springframework.core.Ordered接口,order值越小,切面中定义增强逻辑执行优先级就越高,越先执行。
也就是说:越先织入的越靠近切入点,就越后执行,增强的织入顺序就是切面的order顺序号由大到小的顺序,order序号大的先在靠近切入点的里层织入,order序号小的再向外层层织入,在执行顺序上,先执行外层织入的小order的逻辑,再向内一层层按顺序执行大order逻辑;否则,织入顺序不确定。
4、AOP的实现原理——动态代理
JDK代理——基于接口的代理生成技术 implements
InvocationHandler:增强动作的织手,反射调用-Method.invoke( target, args )
Proxy:基于接口生成门面代理类,Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h).
Cglib代理——基于类的代理生成技术 extends
字节码生成、方法调用拦截、
不能对private/final方法进行代理
两者对比
Cglib创建的代理对象执行性能高于JDK代理(约10倍),生成singleton的代理类推荐使用CGLib技术
CGLib创建代理对象所花费时间多于JDK代理多(约8倍)
5、增强类型
前置增强
后置增强
环绕增强
异常抛出增强
一个方法织入多个异常抛出增强时,Spring会自动选择最匹配的增强方法。在类的继承树上,两个类的距离越近,两个类的相似度越高。目标方法抛出异常后,优先选取拥有异常入参和抛出的异常相似度最高的afterThrowing( )方法。
引介增强——对类横向扩展接口实现