Spring AOP的实现原理
AOP概念介绍
所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程。
关注点: 重复代码就叫做关注点
业务代码:核心业务的代码
切面:
- 关注点形成的类就叫切面(类)!
- 面向切面编程就是指对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。
切入点(拦截的作用):
- 执行目标对象方法,动态植入切面代码。
- 可以通过切入点表达式,指定拦截哪些类的哪些方法,给指定的类在运行的时候植入切面类代码。
功能: 让关注点代码与业务代码分离。
业务代码与关注点代码分离,好处?
- 关注点代码写一次即可;
- 开发者只需要关注核心业务;
- 运行时期,执行核心业务代码时候动态植入关注点代码; 【代理】
如何分离?
过程式/对象式/代理模式分离
AOP的好处是可以动态地添加和删除在切面上的逻辑而不影响原来的执行代码。
AOP的实现原理
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。
如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类。注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
Spring对AOP的支持
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。
Spring创建代理的规则为:
- 默认使用JDK动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了。
- 当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB。
AOP编程其实是很简单的事情,程序员只需要参与三个部分:
- 定义普通业务组件
- 定义切入点,一个切入点可能横切多个业务组件
- 定义增强处理,增强处理就是在AOP框架为普通业务组件织入的处理动作
所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理
即:代理对象的方法=增强处理+被代理对象的方法。
实现AOP编程
注解方式实现AOP编程
步骤:
1) 先引入aop相关jar文件
spring-aop-3.2.5.RELEASE.jar aopalliance.jar aspectjweaver.jar aspectjrt.jar
2) bean.xml中引入aop名称空间
3) 开启aop注解
4) 使用注解
@Aspect 指定一个类为切面类
@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式
@Before("pointCut_()") 前置通知: 目标方法之前执行
@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
@Around("pointCut_()") 环绕通知: 环绕目标方法执行
代码示例:
1、bean.xml中引入aop名称空间
2、开启aop注解
3、指定切面类
4、目标对象类一:实现接口
目标对象类二:没有实现接口
5、测试类
输出结果:
开始事务/异常
-----核心业务:保存!!!------
提交事务/关闭
XML方式实现AOP编程
Xml实现aop编程:
1) 引入jar文件 【aop 相关jar, 4个】
2) 引入aop名称空间
3)aop 配置
* 配置切面类 (重复执行代码形成的类)
* aop配置
拦截哪些方法 / 拦截到方法后应用通知代码
代码示例:
bean.xml配置
全部使用xml配置后,类中注解全部去掉,代码同上