Spring源码探险之@EnableAspectJAutoProxy 是如何启用AOP的

@EnableAspectJAutoProxy 源码如下,它导入了AspectJAutoProxyRegistrar类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
​
    boolean proxyTargetClass() default false;
​
    boolean exposeProxy() default false;
​
}

打开AspectJAutoProxyRegistrar类,它实现了ImportBeanDefinitionRegistrar接口的registerBeanDefinitions方法,从而向容器中注册其他的BeanDefinition。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
​
    /**
     * 注册配置AOP自动代理
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
​
        ...
    }
​
}

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);从方法名可以看出来这里面要注册AspectJAnnotationAutoProxyCreator类的BeanDefinition,点开看一下

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}

继续点,真的注册了AnnotationAwareAspectJAutoProxyCreator.class类的BeanDefinition

@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {
​
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

继续进入registerOrEscalateApcAsRequired

public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
    "org.springframework.aop.config.internalAutoProxyCreator";
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
    Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
​
    ...
    /* 如果已经存在名字为org.springframework.aop.config.internalAutoProxyCreator的BeanDefinition, 判断是否覆盖之前的注册
    */
    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }
    
    /*
    创建beanDefinition并返回,以完成注册
    */
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

现在AnnotationAwareAspectJAutoProxyCreator.class类的BeanDefinition已经完成注册。那么AnnotationAwareAspectJAutoProxyCreator.class类有什么用呢?

先看一下这个类的继承关系

AnnotationAwareAspectJAutoProxyCreator实现的最顶级的接口有

  1. BeanPostProcessor

  2. Aware

  3. Ordered

  4. AopInfrastructureBean

  5. Serializable

比较重要的是BeanPostProcessor和Aware这两个接口。Aware接口用来接收一些容器对象的生命周期的通知。因此猜测应该是在BeanPostProcessor及其子接口的实现方法中完成的AOP

AnnotationAwareAspectJAutoProxyCreator与BeanPostProcessor及其子接口继承关系是

AnnotationAwareAspectJAutoProxyCreator < SmartInstantiationAwareBeanPostProcessor < InstantiationAwareBeanPostProcessor < BeanPostProcessor

BeanPostProcessor 接口有下面两个方法

postProcessBeforeInitialization
postProcessAfterInitialization

InstantiationAwareBeanPostProcessor 接口中有这几个方法

postProcessBeforeInstantiation
postProcessAfterInstantiation
// 这两个看起来是监听属性的,应该不重要
postProcessProperties
postProcessPropertyValues

SmartInstantiationAwareBeanPostProcessor 接口有这几个方法,看起来似乎都不是实现AOP的关键方法

predictBeanType
determineCandidateConstructors
getEarlyBeanReference

所以,可以推测AnnotationAwareAspectJAutoProxyCreator中实现AOP的关键方法是

postProcessBeforeInitialization
postProcessAfterInitialization
postProcessBeforeInstantiation
postProcessAfterInstantiation

打开AnnotationAwareAspectJAutoProxyCreator类,它的方法列表如下,没有猜测的关键方法

setIncludePatterns
setAspectJAdvisorFactory
initBeanFactory
findCandidateAdvisors
isInfrastructureClass
isEligibleAspectBean

打开它的父类AspectJAwareAdvisorAutoProxyCreator看看,AspectJAwareAdvisorAutoProxyCreator的方法列表如下,还是没有

sortAdvisors
extendAdvisors
shouldSkip

继续向上找AspectJAwareAdvisorAutoProxyCreator的父类AbstractAutoProxyCreator方法列表如下,还是没有

setBeanFactory
initBeanFactory
getAdvicesAndAdvisorsForBean
findEligibleAdvisors
findCandidateAdvisors
findAdvisorsThatCanApply
isEligibleAdvisorBean
sortAdvisors
extendAdvisors
advisorsPreFiltered

继续向上找AbstractAutoProxyCreator的父类AbstractAutoProxyCreator

AbstractAutoProxyCreator中可以找到postProcessAfterInitialization和postProcessBeforeInstantiation方法,AbstractAutoProxyCreator再往上找就是SmartInstantiationAwareBeanPostProcessor接口了,所以应该就是这两个方法了

postProcessBeforeInstantiation,注释说这段代码的逻辑是如果有自定义的TargetSource就创建一个代理。因此这里应该是实现Spring AOP TargetSource机制的地方。现在追的是普通的AOP的实现flow,因此这个方法也不是重点

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // Create proxy here if we have a custom TargetSource.
    // Suppresses unnecessary default instantiation of the target bean:
    // The TargetSource will handle target instances in a custom fashion.
    TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    if (targetSource != null) {
        if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
        }
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
        Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    return null;
}

postProcessAfterInitialization,它的重点是调用了wrapIfNecessary方法

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

wrapIfNecessary方法,可以看到注解:Create proxy if we have advice. 应该就是这里了

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return 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.
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

到此,推测应该出是postProcessAfterInitialization方法实现了AOP机制,postProcessAfterInitialization的执行时机如下图,再调用自定义的init-method之后

img

接下来,我们先给这个方法打上断点,创建一个切面类,看看执行流程

package com.example.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAspect {

    @Pointcut("execution(* com.example..*.*(..))")
    public void pointcut(){}

    @Before("pointcut()")
    public void before() {
        System.out.println("before");
    }

}
package com.example.controller;

import org.springframework.stereotype.Component;

@Component
public class HelloController {

    public void sayHello() {
        System.out.println("hello");
    }

}

开始debug。会看到确实有执行到postProcessAfterInitialization方法,并返回了织入切面之后的代理类。

至此已经能够分析出@EnableAspectJAutoProxy 是如何启用AOP的

总结一下流程

  1. @EnableAspectJAutoProxy导入了AspectJAutoProxyRegistrar类

  2. AspectJAutoProxyRegistrar类向Spring注册了AnnotationAwareAspectJAutoProxyCreator类

  3. AnnotationAwareAspectJAutoProxyCreator类实现了BeanPostProcessor 接口,并在postProcessAfterInitialization方法的实现中判断是否为传入的Bean织入切面并生成AOP代理对象

此外,还发现:AnnotationAwareAspectJAutoProxyCreator类实现InstantiationAwareBeanPostProcessor 接口,并在postProcessBeforeInstantiation方法中实现了Spring AOP的Target Source机制

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值