一、什么是AOP?
AOP的全称是 Aspect-Oriented Programming,即面向切面编程(也称面向方面编程)。它是面向对象编程(OOP)的一种补充,目前已成为一种比较成熟的编程方式。
在传统的业务处理代码中,通常会进行事务处理、日志记录等操作。虽然OOP可以通过组合或者继承的方式来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码仍然会分散到各个方法中。这样如果想要关闭某个功能,或者对其进行修改,就必须要修改所有的相关方法。这不但增加了开发人员的工作量,而且提高了代码的出错率。
为了解决这一问题,AOP的思想随之产生。AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,采用传统的OOP思想显然是无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,但不是OOP的替代品,它只是OOP的延伸和补充。
二、原理图
三、AOP相关的概念
1) Aspect :切面,切入系统的一个切面。比如事务管理是一个切面,权限管理也是一个切面;
2) Join point :连接点,也就是可以进行横向切入的位置;
3) Advice :通知,切面在某个连接点执行的操作(分为: Before advice , After returning advice, After throwing advice , After (finally) advice , Around advice );
4) Pointcut :切点,符合切点表达式的连接点,也就是真正被切入的地方;
四、AOP的实现原理
AOP分为静态AOP和动态AOP。
静态AOP是指AspectJ实现的AOP,他是将切面代码直接编译到Java类文件中。
动态AOP是指将切面代码进行动态织入实现的AOP。
Spring的AOP为动态AOP,实现的技术为: JDK提供的动态代理技术 和 CGLIB(动态字节码增强技术) 。尽管实现技术不一样,但 都是基于代理模式,都是生成一个代理对象 。
1 JDK动态代理
主要使用到 InvocationHandler 接口和 Proxy.newProxyInstance() 方法。
JDK动态代理要求被代理实现一个接口,只有接口中的方法才能够被代理 。
其方法是将被代理对象注入到一个中间对象,而中间对象实现InvocationHandler接口,
在实现该接口时,可以在 被代理对象调用它的方法时,在调用的前后插入一些代码。
而 Proxy.newProxyInstance()
能够利用中间对象来生产代理对象。
插入的代码就是切面代码。所以使用JDK动态代理可以实现AOP。
2 CGLIB (code generate libary)
字节码生成技术实现AOP,其实就是继承被代理对象,然后Override需要被代理的方法,在覆盖该方法时,自然是可以插入我们自己的代码的。
因为需要Override被代理对象的方法,所以自然CGLIB技术实现AOP时,就 必须要求需要被代理的方法不能是final方法,因为final方法不能被子类覆盖 。