AOP的实现过程 - 前言

主业务在A类中,辅助业务在切面B类中,在Spring项目的启动过程中,会将A和B类“组合”成一个新的类C,C在执行A的主业务逻辑时,在恰当的时机,会调用B中的方法,C就是代理类。

  • 主业务类A叫做目标类,A中的方法叫做目标方法
  • 辅助业务类B叫做切面,切面(@Aspect)中有切点(@Pointcut)和通知(@Before、@After、@Around等)
  • C类叫做代理类

所以,AOP的实现过程有两个阶段:

  1. 目标对象是如何变成代理对象的?
  2. 代理对象是怎么执行目标方法的?

AOP的实现过程 - 1、目标对象变成代理对象的过程

首先是目标类实例化为目标对象,这个过程是IoC容器初始化、创建bean的过程。

相关方法调用

doCreateBean -> initializeBean

来看一下AbstractAutowireCapableBeanFactorydoCreateBean方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 先尝试从缓存中取
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 调用构造方法创建一个空实例对象,并用BeanWrapper进行包装
instanceWrapper = createBeanInstance(beanName, mbd, args);
}

// 在这里,目标类A的bean被创建出来,此时仅仅是一个内存空间,属性值都是默认的初始零值
Object bean = instanceWrapper.getWrappedInstance();

... // 中间代码省略

// 开始对Bean实例进行初始化
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 对bean进行属性填充,在这里面完成依赖注入的相关内容
populateBean(beanName, mbd, instanceWrapper);

// 如果bean被aop“切”了,在initializeBean方法中bean会变成代理对象返回!!!
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}

... // 后续代码省略
}

先有的目标类bean,然后再为其创建代理对象。

initializeBean -> applyBeanPostProcessorsAfterInitialization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// AbstractAutoWireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 如果实现了Aware接口,就对该bean进行一些设置
// 比如实现了BeanNameAware接口,那么对其bean的属性beanName上设置对应的beanName
// 如果实现了BeanFactoryAware接口,那么对其beanFactory属性设置上创建该bean使用的bean工厂
invokeAwareMethods(beanName, bean);

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
// 如果bean实现了InitializingBean或者用户自定义的init方法方法,那么调用这些初始化方法对bean的属性进行一些个性化设置
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 执行后置处理器的postProcessAfterInitialization方法。AOP的原理和实现就在其中!!!
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}

// AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
// 初始化返回结果为existingBean
Object result = existingBean;

// 遍历所有的 beanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 在 bean 上执行每一个 beanPostProcessor 的 postProcessAfterInitialization() 方法。
Object current = processor.postProcessAfterInitialization(result, beanName);

if (current == null) {
return result;
}
result = current;
}
return result;
}

bean被创建后,会调用所有的BeanPostProcessor作用在bean上,其中有一个名叫AnnotationAwareAspectJAutoProxyCreator的BeanPostProcessor,是它将bean变成了对应的代理类

AnnotationAwareAspectJAutoProxyCreator类

先看下AnnotationAwareAspectJAutoProxyCreator的类关系图:

postProcessAfterInitialization -> wrapIfNecessary

接下来看下代理对象是怎么生成的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// interface BeanPostProcessor#postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
// AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 如果是普通bean,则返回beanName,如果是FactoryBean,则返回加上前缀&的&beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);

// earlyProxyReferences中缓存的是已经创建好的代理对象
// 如果 bean 已经生成了代理,那就跳过,不再重复生成。
// 为什么要判断 bean 是否已经生成了代理?
// 因为在工程启动过程中有两个地方可以将目标对象变成 aop 代理:一个在这里;另一个是目标对象从三级缓存转到二级缓存的时候
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// wrapIfNecessary方法为 bean 创建代理对象并返回。
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

// AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 看看有没有缓存,有缓存对象就直接返回了
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 如果该bean不需要被代理,则直接返回原始的bean对象
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// Create proxy if we have advice.
// 获取 bean 的 advices(通知或增强器),每一个通知都会被构建成一个增强器
// getAdvicesAndAdvisorsForBean 获取切面信息
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

// 判断 specificInterceptors 不为空。如果不为空,说明当前 bean 被”切“了。
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 通过createProxy方法创建代理对象!!!
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

// 如果拿不到 advices,标识 bean 不需要增强。(都没被切,增强个毛线)
this.advisedBeans.put(cacheKey, Boolean.FALSE);

// 返回 bean 或者 bean的代理对象。
return bean;
}

wrapIfNecessary判断有没有针对当前bean的切面。如果没有,直接将bean返回;如果有,为bean创建代理对象。

思考一下问题:

  1. 切面信息是怎么拿到的?更确切的说,切面是怎么被解析的
  2. 怎么判断有没有针对当前bean的切面?其实找的是有没有作用在当前bean上的通知。

获取切面信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean
// 但是因为被继承了,所以此时应该是是在 AnnotationAwareAspectJAutoProxyCreator.java 中
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 为 beanClass 寻找符合条件的增强器(advisors),增强器就是通知,这个后面有解释。
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
// 如果找不到
if (advisors.isEmpty()) {
// 返回 null
return DO_NOT_PROXY;
}
// 找到了增强器,以数组格式将这些增强器返回。
return advisors.toArray();
}

// AbstractAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有的 advisors,包括事务的 advisor 和 普通 aop 的 advisor。。
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 在所有的 advisors 中筛选符合 beanClass 使用的 advisor。(通过切点那块的表达式判定有没有切到 beanClass)
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 向 eligibleAdvisors 中额外再添加一个 ExposeInvocationInterceptor 类型的 advisor。
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 如果有多个 advisor,谁先谁后,在这里排序。
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
// 返回符合条件的 advisor
return eligibleAdvisors;
}

// 这里一定要进到 AnnotationAwareAspectJAutoProxyCreator.java 中,走错地方就找不到这个方法了。
protected List<Advisor> findCandidateAdvisors() {
// 这是是找事务相关的 advisor。因为事务相关的 advisor 少,而且是现成的。
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();

// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 接下来才找 aspectJ 的 advisor。
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
// 返回找到的所有通知。
return advisors;
}

切面是怎么被解析的

切面@Aspect最开始也只是个class文件,只有被注入、解析后才能使用。
大概简述下切面被注入和解析的思路:

  1. 切面被注入的过程:
    切面类上有@Component注解,所以在工程启动时ConfigurationClassPostProcessor会加载切面的class文件,创建对应的BeanDefinition,为其创建对应的bean保存到applicationContext中的beanFactory属性的beanDefinitionMap中,切面就这样被注入了。
  2. 解析切面,最终解析到切面的通知上去,因为辅助的aop逻辑都在通知里面
    beanFactory中拿所有的object的beanName,即获取所有bean的名字,为每一个beanName创建Class对象,判断该Class对象上有没有@Aspect注解,如果有,那这个类就是切面类。
    获取类中的方法,判断类的方法上有没有@Before、@After、@Around等注解,如果有,那这个方法就是通知,为每一个通知创建一个Advisor对象,将所有的Advisor对象保存到advisors列表中。

解析切面的执行时机

todo

筛选作用于当前bean的增强器

todo

创建代理对象

目标类的bean有了,作用在这个bean上的增强器也找到了,接下来就是拿着这两个东西创建代理对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}

// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);

//
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 将目标对象和它的增强器都 set 到 代理工厂中
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}

// 代理工厂创建代理对象,并返回
return proxyFactory.getProxy(getProxyClassLoader());
}

代理工厂返回的是AopProxy接口,它有两个实现CglibAopProxyJdkDynamicAopProxy。至于创建的到底是哪一个,要根据条件判断的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// ProxyFactory#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
// ProxyFactory#getProxyClass
public Class<?> getProxyClass(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxyClass(classLoader);
}

// AopProxy#getProxy
Object getProxy(@Nullable ClassLoader classLoader);
// JdkDynamicAopProxy#getProxy
// CglibAopProxy#getProxy

// DefaultAopProxyFactory implements AopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 获得被代理类的类型,以确定代理的方式
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
//如果目标类有接口,或者本身就是一个代理类,或者是lambada表达式生成的类
//以上三种情况走jdk代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则使用CGLIB生成代理对象
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}

AnnotationAwareAspectJAutoProxyCreator是怎么被加载的?

前面写到AnnotationAwareAspectJAutoProxyCreator解析了切面,创建了增强器,最后将目标对象变成了代理对象,那这个类是怎么被加载到的呢?

1
2
3
4
5
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {}
  1. @EnableAspectJAutoProxy注解将AnnotationAwareAspectJAutoProxyCreator的beanDefinition注入了applicationContext中。
  2. 接下来通过 beanDefinition 创建对应 bean 的过程,AnnotationAwareAspectJAutoProxyCreator的bean也就注入了applicationConext中。
  3. AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,所以在对目标类的 bean 执行初始化时,会调用所有的 BeanPostProcessor,当然少不了 annotationAwareAspectJAutoProxyCreator,它执行 postProcessAfterInitialization(Object bean, String beanName) 方法,将目标类变成了代理类。(它解析切面的时机,不在赘述了)
  4. 至于@Import 注解是什么时候执行的,不用猜都知道它在 ConfigurationClassPostProcessor 类的processConfigBeanDefinitions() 方法中执行的。

AOP的实现过程 - 2、代理对象执行目标方法的过程

代理对象创建好了,最关键的时刻来了:代理对象执行目标方法并在恰当时机将通知织入