Spring AOP
说明
通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP
Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中
什么是AOP
AOP(Aspect Orient Programming),也就是面向切面编程
面向对象编程(OOP)是从静态角度考虑程序结构, 面向切面编程(AOP)是从动态角度考虑程序运行过程
AOP的作用
处理一些具有横切性质的系统性服务,如事务管理、安全检查、缓存、对象池管理等
AOP的实现原理
AOP 实际上是由目标类的代理类实现的。AOP 代理其实是由AOP 框架动态生成的一个对象,该对象可作为目标对象使用
AOP 代理包含了目标对象的全部方法,但AOP 代理中的方法与目标对象的方法存在差异,AOP 方法在特定切入点添加了增强处理,并回调了目标对象的方法
AOP实现
1.静态AOP
机制:静态织入
原理:在编译期,切面直接以字节码的形式编译到目标字节码文件中
优点:对系统无性能影响
缺点:灵活性不够
2.动态AOP
机制:动态代理
原理:在运行期,目标类加载后,为接口动态生成代理类,将切面植入到代理类中
优点:相对于静态AOP更加灵活
缺点:切入的关注点需要实现接口。对系统有一点性能影响
代表:JDK动态代理
接口 + InvocationHandler + 目标对象 = 代理
3.动态字节码生成
机制:在运行期,目标类加载后,动态构建字节码文件生成目标类的子类,将切面逻辑加入到子类中
原理:没有接口也可以织入
优点:扩展类的实例方法为final时,则无法进行织入
代表:Cglib动态代理(依赖ASM)
接口或类 + MethodInterceptor + 目标对象 = 代理
4.自定义加载器
机制:在运行期,目标加载前,将切面逻辑加到目标字节码里
原理:可以对绝大部分类进行织入
优点:代码中如果使用了其他类加载器,则这些类将不会被织入
代表:Javassist
5.字节码转换
机制:在运行期,所有类加载器加载字节码前,前进行拦截
原理:可以对所有类进行织入
代表:Javassit + Instrumentation
Spring对AOP的支持
Spring 中AOP 代理由Spring 的IoC 容器负责生成、管理,其依赖关系也由IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他Bean 实例作为目标,这种关系可由IoC 容器的依赖注入提供
Spring 默认使用Java 动态代理来创建AOP 代理, 这样就可以为任何接口实例创建代理了。当需要代理的类不是代理接口的时候, Spring 自动会切换为使用CGLIB 代理,也可
强制使用CGLIB
AOP 编程
定义普通业务组件
定义切入点,一个切入点可能横切多个业务组件
定义增强处理,增强处理就是在AOP 框架为普通业务组件织入的处理动作
所以进行AOP 编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP 框架将会自动生成AOP 代理,即:代理对象的方法 = 增强处理 + 被代理对象的方法
Spring中AOP的实现
1.基于Annotation 的“零配置”方式:使用@Aspect、@Pointcut 等Annotation 来标注切入点和增强处理
a.首先启用Spring 对@AspectJ 切面配置的支持
b.定义切面Bean
当启动了@AspectJ 支持后,只要在Spring 容器中配置一个带@Aspect 注释的Bean, Spring 将会自动识别该Bean 并作为切面处理
c.定义@Before 增强处理
d.定义@AfterReturning 增强处理
e.定义@AfterThrowing 增强处理
f.定义@After 增强处理
After 增强处理与AfterReturning 增强处理有点相似,但也有区别
AfterReturning 增强处理处理只有在目标方法成功完成后才会被织入
After增强处理不管目标方法如何结束(保存成功完成和遇到异常中止两种情况),它都会被织入
g.@Around 增强处理
h.访问目标方法的参数
i.定义切入点
所谓切入点,其实质就是为一个切入点表达式起一个名称,从而允许在多个增强处理中重用该名称
一个切入点表达式
一个包含名字和任意参数的方法签名
2.基于XML 配置文件的管理方式:使用Spring 配置文件来定义切入点和增强点
使用Spring ProxyFactoryBean创建代理
使用 ProxyFactoryBean 来创建 AOP 代理的最重要的优点之一是 IoC 可以管理通知和切入点。 这是一个非常的强大的功能,能够实现其他 AOP 框架很难实现的特定的方法。例如,一个通知本身可以引用应用对象(除了目标对象,它在任何 AOP 框架中都可以引用应用对象),这完全得益于依赖注入所提供的可插入性
a.ProxyFactoryBean的proxyInterfaces属性,指明要代理的接口
b.ProxyFactoryBean的target属性,指明要代理的目标类 ,这个目标类实现了上面proxyInterfaces属性指定的接口
c.ProxyFactoryBean的interceptorNames属性,指明要在代理的目标类中插入的Adivce
d.ProxyFactoryBean还有一个proxyTargetClass属性,如果这个属性被设定为“true”,说明 ProxyFactoryBean要代理的不是接口类,而是要使用CGLIB方式来进行代理,后面会详细讲解使用CGLIB方式来进行代理
IntroductionIntercepter
影响了目标物件的行为定义,直接增 加了目标物件的职责