上一篇介绍了实现AOP的两种方式,本篇我们通过分析源码流程,来看一下注解版AOP的实现。具体的源码细节,会在后面的篇章一行行翻译。
1.开启AOP的功能
读源码需要找到入口或者抓手,AOP的源码我们如何入手呢?想要使用AOP的功能就需要在Spring的配置类上加上**@EnableAspectJAutoProxy**
注解。
先分析一下这个注解:
�
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* 是否要创建基于子类 (CGLIB) 的代理,而不是基于标准 Java 接口的代理。 默认值为false 。
* @return
*/
boolean proxyTargetClass() default false;
/**
* 代理应由 AOP 框架公开为ThreadLocal以通过AopContext类进行检索。
* 默认关闭,即不保证AopContext访问将起作用。
*/
boolean exposeProxy() default false;
}
可以看到这个注解的底层有一个**@Import(AspectJAutoProxyRegistrar.class)**
,他往容器中导入了一个组件**AspectJAutoProxyRegistrar**
。
看一下这个组件:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
/*导入组件到容器中 AnnotationAwareAspectJAutoProxyCreator*/
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
/*
* 参数一:固定类型
* 参数二:spring容器
* 参数三:标签
* */
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
�
�**AspectJAutoProxyRegistrar**
实现了 **ImportBeanDefinitionRegistrar**
接口,往容器中注册了一个bd信息。**AnnotationAwareAspectJAutoProxyCreator**
2.加载时机
�
上一节我们分析到,在Spring的配置类上打一个注解,最后总会往容器中导入一个类:**AnnotationAwareAspectJAutoProxyCreator**
。
我们来分析一下这个类的继承关系:
按照顺序分析一下这个类的加载时机和加载的时候,里面的 **initBeanFactory()**
& **setBeanFactory()**
是什么时候执行的。
�
- 首先执行的是
**AbstractAdvisorAutoProxyCreator**
的**setBeanFactory()**
。
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
- 接下来执行的是
**AbstractAutoProxyCreator**
的**setBeanFactory()**
。
�
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
- 然后执行的是
**AnnotationAwareAspectJAutoProxyCreator**
的**initBeanFactory()**
。
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
- 最终执行的是
**AbstractAdvisorAutoProxyCreator**
的**initBeanFactory()**
。
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
接下来分析**AnnotationAwareAspectJAutoProxyCreator**
的执行时机。
3.创建代理对象
4.获取拦截器
5.链式调用通知方法
6.流程总结
AOP其实就是往容器中导入了一个组件,这个组件是一个后置处理器,他会在对象创建之前尝试返回一个代理对象,如果不能成功返回,会在对象创建之后,init方法执行前后去判断当前对象是否需要被代理,如果需要被代理则根据各种条件去选择代理方式,创建代理对象,同时会去判断哪些切面和方法需要增强代理对象里面的方法,生成一条拦截器链。 � �在代理对象执行目标方法前后,通过拦截器对目标方法进行拦截,执行增强逻辑。