共计 1077 个字符,预计需要花费 3 分钟才能阅读完成。
一、What?
AOP, 面向切面编程
- OOP 面向对象编程的模式,OOP 的主要功能是数据封装、继承和多态。OOP 把系统看作多个对象的交互
- AOP 是一种新的编程方式,AOP 把系统分解为不同的关注点,或者称之为切面
相关概念:
- Aspect:切面,即一个横跨多个核心逻辑的功能,或者称之为系统关注点
- Joinpoint:连接点,即定义在应用程序流程的何处插入切面的执行
- Pointcut:切入点,即一组连接点的集合
- Weaving:织入,指将切面整合到程序的执行流程中
- Target Object:目标对象,即真正执行业务的核心逻辑对象
拦截器有以下类型:
- @Before:这种拦截器先执行拦截代码,再执行目标代码。如果拦截器抛异常,那么目标代码就不执行了;
- @After:这种拦截器先执行目标代码,再执行拦截器代码。无论目标代码是否抛异常,拦截器代码都会执行;
- @AfterReturning:和 @After 不同的是,只有当目标代码正常返回时,才执行拦截器代码;
- @AfterThrowing:和 @After 不同的是,只有当目标代码抛出了异常时,才执行拦截器代码;
- @Around:能完全控制目标代码是否执行,并可以在执行前后、抛异常后执行任意拦截代码,可以说是包含了上面所有功能。
二、How?
生产中使用注解装配 AOP,不要使用 AspectJ 的类似 execution( xxx.Xyz.(..)) 这样的复杂注解
三、Why?
对于 AOP 的织入,有 3 种方式:
- 编译期:在编译时,由编译器把切面调用编译进字节码,这种方式需要定义新的关键字并扩展编译器,AspectJ 就扩展了 Java 编译器,使用关键字 aspect 来实现织入;
- 类加载器:在目标类被装载到 JVM 时,通过一个特殊的类加载器,对目标类的字节码重新“增强”;
- 运行期:目标对象和切面都是普通 Java 类,通过 JVM 的动态代理功能或者第三方库实现运行期动态织入。
Spring 的 AOP 实现就是基于动态代理:
- Spring 对接口类型使用 JDK 动态代理,对普通类使用 CGLIB 创建子类。如果一个 Bean 的 class 是 final,Spring 将无法为其创建子类。
自动加 super() 的功能是 Java 编译器实现的,它发现你没加,就自动给加上,发现你加错了,就报编译错误。但实际上,如果直接构造字节码,一个类的构造方法中,不一定非要调用 super()。Spring 使用 CGLIB 构造的 Proxy 类,是直接生成字节码,并没有源码 - 编译 - 字节码这个步骤, 所以:
- Spring 通过 CGLIB 创建的代理类,不会初始化代理类自身继承的任何成员变量,包括 final 类型的成员变量!
正文完