Java AOP
AOP知识整理
AOP(Aspect-Oriented Programming):面向切面的编程。OOP(Object-Oriented Programming)面向对象的编程。对于OOP我们已经再熟悉不过了,对于AOP,可能我们会觉得是一种新特性,其实AOP是对OOP的一种补充,OOP面向的是纵向编程,继承、封装、多态是其三大特性,而AOP是面向横向的编程。
面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足。在OOP中模块化的关键单元是类(classes),而在AOP中模块化的单元则是切面。切面能对关注点进行模块化,例如横切多个类型和对象的事务管理。
AOP框架是spring的一个重要组成部分。但是Spring IoC容器并不依赖于AOP,这意味着你有权利选择是否使用AOP,AOP做为Spring IoC容器的一个补充,使它成为一个强大的中间件解决方案。
AOP在Spring Framework中的作用
1.AOP概念:
学习AOP,当然得先了解一下其众多的概念性术语:
通知类型:
环绕通知是最常用的通知类型。和AspectJ一样,Spring提供所有类型的通知,我们推荐你使用尽可能简单的通知类型来实现需要的功能。例如,如果你只是需要一个方法的返回值来更新缓存,最好使用后置通知而不是环绕通知,尽管环绕通知也能完成同样的事情。用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误。比如,你不需要在JoinPoint上
调用用于环绕通知的proceed()方法,就不会有调用的问题。
在这里,基于@AspectJ的AOP我就不多写了,因为我更青睐于Spring中使用ProxyFactoryBean创建AOP代理。
2.使用ProxyFactoryBean创建AOP代理:
在Spring里创建一个AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean。 这个类对应用的切入点和通知提供了完整的控制能力(包括它们的应用顺序)。像其它的FactoryBean实现一样,ProxyFactoryBean引入了一个间接层。如果你定义一个名为foo的ProxyFactoryBean, 引用foo的对象看到的将不是ProxyFactoryBean实例本身,而是一个ProxyFactoryBean实现里getObject() 方法所创建的对象。 这个方法将创建一个AOP代理,它包装了一个目标对象。
ProxyFactoryBean类本身也是一个JavaBean,其属性主要有如下用途:
一些主要属性从org.springframework.aop.framework.ProxyConfig里继承下来(这个类是Spring里所有AOP代理工厂的父类)。这些主要属性包括:
ProxyFactoryBean中需要说明的其它属性包括:
这里的名字是当前工厂中bean的名字,包括父工厂中bean的名字。这里你不能使用bean的引用因为这会导致ProxyFactoryBean忽略通知的单例设置。
你可以把一个拦截器的名字加上一个星号作为后缀(*)。这将导致这个应用程序里所有名字以星号之前部分开头的通知器都被应用。
单例:工厂是否应该返回同一个对象,不论方法getObject()被调用的多频繁。 多个FactoryBean实现都提供了这个方法。缺省值是true。 如果你希望使用有状态的通知--例如,有状态的mixin--可以把单例属性的值设置为false来使用原型通知。
3.基于JDK和CGLIB的代理:
如果一个需要被代理的目标对象的类(后面将简单地称它为目标类)没有实现任何接口,那么一个基于CGLIB的代理将被创建。 这是最简单的场景,因为JDK代理是基于接口的,没有接口意味着没有使用JDK进行代理的可能.
如果ProxyFactoryBean的proxyTargetClass属性被设为true,那么一个基于CGLIB的代理将创建。 这样的规定是有意义的,遵循了最小惊讶法则(保证了设定的一致性)。甚至当ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名, 而proxyTargetClass属性被设置为true仍然将实际使用基于CGLIB的代理。
如果ProxyFactoryBean的proxyInterfaces属性被设置为一个或者多个全限定接口名,一个基于JDK的代理将被创建。 被创建的代理将实现所有在proxyInterfaces属性里被说明的接口; 如果目标类实现了全部在proxyInterfaces属性里说明的接口以及一些额外接口,返回的代理将只实现说明的接口而不会实现那些额外接口。
如果ProxyFactoryBean的proxyInterfaces属性没有被设置, 但是目标类实现了一个(或者更多)接口,那么ProxyFactoryBean将自动检测到这个目标类已经实现了至少一个接口, 一个基于JDK的代理将被创建。被实际代理的接口将是目标类所实现的全部接口; 实际上,这和在proxyInterfaces属性中列出目标类实现的每个接口的情况是一样的。 然而,这将显著地减少工作量以及输入错误的可能性。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!