AOP可以理解为是在业务主线上加入必不可少的琐碎且重复的小事。
Spring Aop 是使用典型的动态代理模式来实现的。 就代理模式而言,我们将必不可少的琐碎且重复的小事交给一个对象去完成,这个对象我们称他为代理对象。而完成主要工作的对象,我们这儿称为目标对象。
在jdk动态代理中,实际上是运用了JDK的API。在内存中创建了一个与目标对象实现同一接口的代理对象。所以目标对象一定是实现了某一个接口才可以进行代理。
那没有实现接口的怎么办?
在Spring Aop中,没有实现接口的对象使用cglib动态代理来实现代理。cglib与jdk动态代理一样,都是在内存中动态的生成一个代理对象。不同的是,JDK创建的是与目标对象实现同一个接口的代理对象,而cglib创建的是目标对象的子类对象作为代理对象。由此可得出他的缺点,不能代理final类,会报错。因为final修饰的类不可以被继承。final/static修饰的方法不会报错,但是不会进行代理。
下表是两者区别的概括:
| 目标对象 | jdk代理 | cglib代理 |
|---|---|---|
| 类型 | 同一接口的子类 | 目标对象的子类 |
| 生成方式 | 反射机制 | 字节码处理框架ASM转换字节码 |
| 限制 | 目标对象要实现接口 | 目标对象不能被final修饰 |
提到Spring Aop,到这里应该就差不多了,但是我发现网上很多声音在说AspectJ,这里就对这一块内容进行补充一下。 AspectJ是一种AOP框架,它可以在编译期构建代理对象,但是他需要特殊的编译器(AJC)。可以说AspectJ是目前实现AOP框架中最成熟,功能最丰富的语言。Spring的大佬们就眼馋了,我得借鉴借鉴是吧。于是把AspectJ的一套注解搬到了Spring Aop中,但是因为底层实现是依赖AJC编译器,所以舍弃了这个,采用动态代理(JDK或者CGLib)来实现。