AOP的概念和使用原因
- 概念
现实中有一些内容并不是面向对象(OOP)可以解决的,比如数据库事务,它对于企业级的Java EE应用而言十分重要,比如在电商网站购物中需要经过交易系统、财务系统,对于交易系统存在一个交易记录的对象,而在财务系统中则存在账户的信息对象。从这个角度而言,我们需要保证交易记录和账户操作形成一个统一的事务管理。 - 使用原因
要保证两个对象在同一个事务中控制,这就不是面向对象可以解决的问题,需要用到面向切面的编程,这里的切面环境就是数据库事务。
关于事务的约定:
- 当方法标注为@Transactional时,则方法启用数据库事务功能。
- 在默认情况下(注意是默认情况下,可以通过配置改变),如果原有方法出现异常,则回滚事务;如果没有发生异常,那么就提交事务,这样整个事务管理AOP就完成了整个流程,无需开发者编写任何代码去实现。
- 最后关闭数据库资源,这点也比较通用,这里AOP框架也帮你完成它。
作用:
AOP是通过动态代理模式,带来管控各个对象操作的切面环境,管理包括日志、数据库事务等操作,让我们拥有可以在反射原有对象方法之前
正常返回、异常返回事后插入自己的逻辑代码的能力,有时候甚至取代原始方法。
面向切面的术语
- 切面(Aspect)
切面就是在一个怎么样的环境中工作。在动态代理中可以把它理解成一个拦截器。 - 通知(Advice)
通知是切面开启后,切面的方法。它根据在代理对象真实方法调用前、后的顺序和逻辑区分,相当于拦截器。
(1)前置通知(before):在动态代理反射原有对象方法或者执行环绕通知前执行的通知功能。
(2)后置通知(after):在动态代理反射原有对象方法或者执行环绕通知后执行的通知功能。无论是否抛出异常,它都会被执行。
(3)返回通知(afterReturning):在动态代理反射原有对象方法或者执行环绕通知后执行的通知功能。
(4)异常通知(afterThrowing):在动态代理反射原有对象方法或者执行环绕通知产生异常后执行的通知功能。
(5)环绕通知(aroundThrowing):在动态代理中,它可以取代当前被拦截对象的方法,通过参数或反射调用被拦截对象的方法。 - 引入(Introduction)
引入允许我们在现有的类里面添加自定义的类和方法。 - 切点(Pointcut)
在动态代理中,被切面拦截的方法就是一个切点,切面将可以将其切点和被拦截的方法按照一定的逻辑织入到约定的流程中。 - 连接点(join point)
连接点是一个判断条件,由它可以指定哪些是切点。对于指定的切点,Spring 会生成代理对象去使用对应的切面对其拦截,否则就不会拦截它。 - 织入(Weaving)
织入是一个生成代理对象的过程。实际代理的方法分为静态代理和动态代理。
静态代理是在编译class文件时生成的代码逻辑,但是在Spring中并不使用这样的方式,所以我们pass。
一种是通过ClassLoader也就是在类加载的时候生成的代码逻辑,但是它在应用程序代码运行前就生成对应的逻辑。
还有一种是运行期,动态生成代码的方式,这就是Spring AOP所采用的方式,Spring是以JDK和CGLIB动态代理来生成代理对的。
Spring对AOP的支持
在Spring中有4种方式去实现AOP的拦截功能。
(1)使用ProxyFactoryBean和对应的接口实现AOP
(2)使用XML配置AOP
(3)使用@AspectJ注解驱动切面
(4)使用AspectJ注入切面
在Spring AOP的拦截方法中,真正常用的是用@AspectJ注解的方式实现的切面,有时候XML配置也有一定的辅助作用。
其中ProxyFactory和AspectJ注入切面的方式很少用。