https://www.cnblogs.com/kukudelaomao/p/5897893.html
AOP是Aspect Oriented Programing的简称,面向切面编程。AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录。AOP将这些分散在各个业务逻辑中的
通过横向切割的方式抽取到一个独立的模块中。
一、AOP术语
1.连接点(Joinpoint)
程序执行的某个特定位置:如类开始初始化之前、类初始化之后、类某个方法调用前、调用后等;一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就成为“连接点”,Spring仅支持方法的连接点,即仅能在方法调用前、方法调用后以及方法调用前后的这些程序执行点织入增强。比如:黑客攻击系统需要找到突破口,没有突破口就没有办法攻击,从某种程度上来说,AOP就是一个黑客,连接点就是AOP向目标类攻击的候选点。
连接点有两个信息确定:第一是用方法表示的程序执行点;第二是用相对点表示的方位;如在Test.foo()方法执行前的连接点,执行点为Test.foo,方位为该方法执行前的位置。Spring使用切点对执行点进行定位,而方位则在增强类型中定义。
2.切点(Pointcut)
查询条件,查出来的是多个连接点
每个程序类都拥有许多连接点,如一个拥有两个方法的类,这两个方法都是连接点,即连接点是程序类中客观存在的事物。但在为数众多的连接点钟,如何定位到某个连接点上呢?AOP通过切点定位特定连接点。通过数据库查询的概念来理解切点和连接点:连接点相当于数据库表中的记录,而切点相当于查询条件。连接点和切点不是一一对应的关系,一个切点可以匹配多一个连接点。
3.增强(Advice)
包含增强逻辑+方位
增强是织入到目标类连接点上的一段程序代码(好比AOP以黑客的身份往业务类中装入木马),增强还拥有一个和连接点相关的信息,这边是执行点的方位。结合执行点方位信息和切点信息,我们就可以找到特定的连接点了,所以Spring提供的增强接口都是带方位名的:BefortAdvice、AfterReturningAdvice、ThrowsAdvice等。(有些将Advice翻译为通知,但通知就是把某个消息传达给被通知者,并没有为被通知者做任何事情,而Spring的Advice必须嵌入到某个类的连接点上,并完成了一段附加的应用逻辑;)
4.目标对象(Target)
增强逻辑的织入目标类,如果没有AOP,目标业务类需要自己实现所有逻辑,在AOP的帮助下,目标类只实现那些非横切逻辑的程序逻辑,而其他监测代码则可以使用AOP动态织入到特定的连接点上。
5.引介(Introduction)
引介是一种特殊的增强,它为类添加一些属性和方法,这样即使一个业务类原本没有实现某个接口,通过AOP的引介功能,我们可以动态的为该业务类添加接口的实现逻辑,让这个业务类成为这个接口的实现类。
6.织入(Weaving)
织入是将增强添加到目标类具体连接点上的过程,AOP就像一台织布机,将目标类、增强或者引介编织到一起,AOP有三种织入的方式:
a.编译期间织入,这要求使用特殊的java编译器;
b.类装载期织入,这要求使用特殊的类装载器;
c.动态代理织入,在运行期为目标类添加增强生成子类的方式。
Spring采用动态代理织入,而AspectJ采用编译器织入和类装载期织入。
7.代理(Proxy)
一个类被AOP织入增强后,就产生出了一个结果类,它是融合了原类和增强逻辑的代理类。
8.切面(Aspect)
切面由切点和增强组成,它既包括了横切逻辑的定义,也包括了连接点的定义,Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中。
总结:AOP的工作重点就是如何将增强应用于目标对象的连接点上,这里首先包括两个工作:第一,如何通过切点和增强定位到连接点;第二,如何在增强中编写切面的代码。
代理代码可参考代理模式章节
二、AOP实例(通过Proxy代理模式)
Spring AOP使用纯java实现,不需要专门的编译过程和类装载器,它在运行期间通过代理方式向目标类织入增强代码,它更侧重于提供一种和Spring IoC容器整合的AOP实现,在Spring中,我们可以无缝的将AOP,IoC,AspectJ整合在一起。
Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理;
JDK1.3以后,java提供了动态代理技术,允许开发者在运行期间动态的创建接口的代理实例,JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler,其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。
Spring AOP的底层就是通过代理(JDK动态代理或CGlib代理)来实现AOP的,但是这种实现方式存在三个明显需要改进的地方:
a.目标类的所有方法都添加了横切逻辑,而有时,这并不是我们所期望的,我们可能只希望对业务类中的某些特定的方法添加横切逻辑;
b.我们通过硬编码的方式制定了织入横切逻辑的织入点,即在目标业务方法的开始和结束前织入代码;
c.我们手工编写代理实例的创建过程,为不同类创建代理时,需要分别编写相应的创建代码,无法做到通用;
CGLib所创建的动态代理对象的性能比JDK的高大概10倍,但CGLib在创建代理对象的时间比JDK大概多8倍,所以对于singleton的代理对象或者具有实例池的代理,因为无需重复的创建代理对象,所以比较适合CGLib动态代理技术,反之选择JDK代理。值得一提的是由于CGLib采用动态创建子类的方式生成代理对象,所以不能对目标类中final的方法进行代理。
三、创建增强类
Spring使用增强定义横切逻辑,同时由于Spring只支持方法连接点,增强还包括了在方法的哪一点加入横切代码的方位信息,所以增强既包含横切逻辑,还包含部分连接点的信息。
前置增强:org.springframework.aop.BeforeAdvice 代表前置增强,因为Spring只支持方法级的增强,所以MethodBeforeAdvice是目前可用的前置增强,表示在目标方法执行前实施增强,而BeforeAdvice是为了将来版本扩展需要而定义的,下面我们看一个前置通知的小例子:
说明:在测试代码中,我们用到了org.springframework.aop.framework.ProxyFactory,这个内部就是使用了我们之前的JDK代理或者CGLib代理的技术,将增强应用到目标类中。Spring定义了org.springframework.aop.framework.AopProxy接口,并提供了两个final的实现类,其中:
Cglib2AopProxy使用CGLib代理技术创建代理,而JdkDynamicAopProxy使用JDK代理技术创建代理;
如果通过ProxyFactory的setInterfaces\(Class\[\] interfaces\)指定针对接口进行代理,ProxyFactory就使用JdkDynamicAopProxy;
如果是通过类的代理则使用Cglib2AopProxy,另外也可以通过ProxyFactory的setOptimize\(true\)方法,让ProxyFactory启动优化代理模式,这样针对接口的代理也会使用Cglib2AopProxy。
jdk的底层是AspectJ
cglib底层是netsf的Enhancer