目录
一、概述
- AOP(Aspect Orient Programming):面向切面编程;
用途:用于系统中的横切关注点,比如日志管理,事务管理;
实现:利用代理模式,通过代理对象对被代理的对象增加功能。所以,关键在于AOP框架自动创建AOP代理对象,代理模式分为静态代理和动态代理;
框架:
AspectJ使用静态代理,编译时增强,在编译期生成代理对象;
SpringAOP使用动态代理,运行时增强,在运行时,动态生成代理对象; - AspectJ框架;
经过AspectJ的编译器编译后的java字节码,会比java源码多一些代码,即在编译阶段,将定义的Aspect切面织入Java字节码中,运行时就是已经被增强过的类了;支持到方法、字段,构造器级别; - SpringAOP框架;
区别于AspectJ,Spring AOP使用的是动态代理,不修改字节码,而是运行时在内存中临时创建一个AOP代理对象,AOP对象包含了被代理对象的全部方法,并在特定的切点做了增强处理,回调被代理对象的方法;支持到方法级别;
二、SpringAOP运行时增强
Spring AOP动态代理主要是两种方式,JDK动态代理和CGLIB动态代理。
- JDK动态代理:通过反射来接收被代理的类,并且被代理的类必须实现接口;
核心是:java.lang.reflect.InvocationHandler接口 与 java.lang.reflect.Proxy类; - CGLIB动态代理:目标类没有实现接口,Spring AOP会选择使用CGLIB在运行时动态的生成某个类的子类,因此,CGLIB是通过继承的方式,用子类实现对目标类的增强,final class不可继承的类,无法使用CGLIB做动态代理。
- Spring的AOP与IOC:Spring AOP对象由Spring IOC容器自动生成、管理,其依赖关系也由IOC容器负责管理,那么AOP对象可以直接使用容器中的其他Bean实例作为被代理对象,所以此时使用SpringAOP只需要定义切点(pointcut)和 增强(advice)即可。
- AOP代理的方法通过在目标对象的切入点动态的织入增强处理,完成对目标方法的增强。
三、Spring AOP的常用类

- ProxyConfig类:所有Spring AOP生成的代理对象的基类,主要为其AOP代理对象工厂实现类提供配置属性。
public class ProxyConfig implements Serializable {
private boolean proxyTargetClass = false;
private boolean optimize = false;
boolean opaque = false;
boolean exposeProxy = false;
private boolean frozen = false;
public void copyFrom(ProxyConfig other) {
Assert.notNull(other, "Other ProxyConfig object must not be null");
this.proxyTargetClass = other.proxyTargetClass;
this.optimize = other.optimize;
this.exposeProxy = other.exposeProxy;
this.frozen = other.frozen;
this.opaque = other.opaque;
}
}
- AdvisedSupport类:ProxyConfig类的子类,封装了AOP中通用的对增强(Advice)和通知器(Advisor)的相关操作,对于所有生成AOP代理对象都通用,而代理对象的生成由子类完成;
- ProxyCreatorSupport类:AdvisedSupport类的子类,一个AOP对象创建的辅助类,提供不同的AOP代理对象生成的通用方法,而代理对象的生成由其子类完成。
- 实际创建AOP对象的类:AspectJProxyFactory、ProxyFactory、ProxyFactoryBean;工厂类;ProxyCreatorSupport的子类;
- AspectJProxyFactory:创建AspectJ的AOP对象,用于Spring集成AspectJ的作用,此时,就不需要使用AspectJ特定的编译器了。
- ProxyFactory:创建编程式的AOP对象;
- ProxyFactoryBean:创建声明式的AOP对象,通过配置创建AOP对象;
四、Spring AOP源码分析
以ProxyFactoryBean为例,分析Spring AOP的实现原理。
1.XML 配置
<!-- 切面 --> <bean id="logAdvice" class="com.test.advice.LogAdvice"/>
<!--配置AOP代理工厂,封装AOP功能的主要类--> <bean id="requestProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- AOP 代理接口 --> <property name="proxyInterfaces"> <value>com.test.Request</value> </property> <!-- 需要增强的对象 --> <property name="target"> <bean class="com.test.StringRequest" /> </property> <!--代理拦截器,配置通知器的名称,即通知器在AOP代理的配置下通过使用代理对象的拦截机制发挥作用--> <property name="interceptorNames"> <list> <value>logAdvice</value> </list> </property> <!-- 是否接口类:true说明ProxyFactoryBean要代理的不是接口类,而是CGLIB方式来进行代理 --> <property name="proxyTargetClass" value="false"/> </bean>
2.ProxyFactoryBean生成AOP代理对象
ProxyFactoryBean配置目标对象和切面行为Advice,通过其配置的拦截器名称interceptorNames即通知器Advisor将切面应用到目标对象中。
ProxyFactoryBean的功能:
- 初始化通知器链
- 获取单例、原型的Aop代理对象
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {// 标记通知器的为全局通知器
public static final String GLOBAL_SUFFIX = "*";// 通知器链是否已经初始化
private boolean advisorChainInitialized = false;// 如果是单例,缓存单例对象
private Object singletonInstance;// 实际上是:new DefaultAdvisorAdapterRegistry();Advisor适配器注册,将Advice适配成Advisor
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
// 创建AOPProxy代理对象的入口
public Object getObject() throws BeansException {
// 初始化通知器链
initializeAdvisorChain();if (isSingleton()) { // 单例
return getSingletonInstance();
}
else { // 原型
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}// 初始化通知器链(同步方法)
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
// 如果通知器链已经初始化,直接返回
return;
}if (!ObjectUtils.isEmpty(this.interceptorNames)) { // 如果配置的拦截器名称存在
// 如果没有bean容器,抛出异常
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}// 全局通知器不能是通知器链中最后一个,除非显示的指定了目标
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}// 遍历通知器链名称
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
// 如果通知器是全局的
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
// 向容器中添加全局通知器
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.subs