• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

Spring AOP源码(5)—DefaultAdvisorAutoProxyCreator自动代理创建者

互联网 diligentman 1周前 (02-18) 10次浏览

  基于最新Spring 5.x,详细介绍了DefaultAdvisorAutoProxyCreator的实现原理!

文章目录

  • Spring AOP源码 系列文章
  • DefaultAdvisorAutoProxyCreator原理

Spring AOP源码 系列文章

Spring AOP源码(1)—<aop:config/>AOP配置标签解析

Spring AOP源码(2)—AspectJAwareAdvisorAutoProxyCreator创建代理对象

Spring AOP源码(3)—invoke代理方法的调用与执行增强

Spring AOP源码(4)—基于注解的AOP源码解析以及AnnotationAwareAspectJAutoProxyCreator

Spring AOP源码(5)—DefaultAdvisorAutoProxyCreator自动代理创建者

DefaultAdvisorAutoProxyCreator原理

  此前,我们已经讲解了AspectJAwareAdvisorAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator的源码,它们是最普通(普遍的)Spring AOP的实现原理,因此是最重要的。如果具有<aop:config/>标签,那么默认使用AspectJAwareAdvisorAutoProxyCreator来创建代理,如果具有<aop:aspectj-autoproxy/>标签或者@EnableAspectJAutoProxy注解,那么默认使用AnnotationAwareAspectJAutoProxyCreator来创建代理。
  DefaultAdvisorAutoProxyCreator同样继承了AbstractAdvisorAutoProxyCreator,是四种基于Advisor的自动代理创建者的实现之一:
Spring AOP源码(5)—DefaultAdvisorAutoProxyCreator自动代理创建者
  DefaultAdvisorAutoProxyCreator使用的地方实际上并不是很多,在我们了解了AspectJAwareAdvisorAutoProxyCreator和AnnotationAwareAspectJAutoProxyCreator的源码之后,我们知道Spring AOP的大部分处理流程都是在父类AbstractAutoProxyCreator和AbstractAdvisorAutoProxyCreator中完成的,这些具体的实现类仅仅是重写了某些方法来实现自己的特性,因此DefaultAdvisorAutoProxyCreator的原理也非常的简单!
  DefaultAdvisorAutoProxyCreator和前两个AutoProxyCreator的大概区别如下:

  1. sortAdvisors:用于对已找到的Advisors链进行排序
    1. DefaultAdvisorAutoProxyCreator采用父类AbstractAdvisorAutoProxyCreator的默认sortAdvisors方,基于AnnotationAwareOrderComparator比较器的排序
    2. 另两个AutoProxyCreator则重写了该方法,除了使用AnnotationAwareOrderComparator之外,还是用了aspectName、declarationOrder(声明顺序)来进行排序
  2. extendAdvisors:用于对已找到的Advisors链进行扩展。
    1. DefaultAdvisorAutoProxyCreator采用父类AbstractAdvisorAutoProxyCreator的默认extendAdvisors方法,该方法中什么也没做。
    2. 另两个AutoProxyCreator则重写了该方法,并且在Advisors链的头部添加一个特殊的Advisor——DefaultPointcutAdvisor,其内部的ExposeInvocationInterceptor用于暴露MethodInvocation。
  3. shouldSkip:判断是否需要跳过对给定bean进行的自动代理。
    1. DefaultAdvisorAutoProxyCreator采用父类AbstractAutoProxyCreator的默认shouldSkip方法,逻辑是:如果beanName以beanCassName开头,并且以“.ORIGINAL”结束,那么返回true,表示当前bean应该采用原始实例,禁止代理,否则返回false。
    2. 另两个AutoProxyCreator则重写了该方法,将会通过findCandidateAdvisors方法查找beanFactory中的所有Advisor类型的通知器bean定义并且初始化(这个方法在其他地方也会调用),如果存在AspectJPointcutAdvisor类型的通知器实例,并且beanName等于aspectName,即表示当前的bean属于这个通知器的切面方法类bean,那么不应该拦截切面方法类的方法,直接返回true,表示跳过。否则在最后会才会调用父类的逻辑。
  4. isEligibleAdvisorBean:在findAdvisorBeans(查找候选Advisors)方法中,根据通知器的beanName判断通知器bean是否是合格的候选通知器。
    1. 另两个AutoProxyCreator使用了父类AbstractAdvisorAutoProxyCreator的逻辑,默认始终返回true,也就是不根据名称筛选。
    2. DefaultAdvisorAutoProxyCreator则重写了该方法,支持beanName具有给定前缀的通知器bean才能够算作候选Advisor通知器。这也是DefaultAdvisorAutoProxyCreator最大的功能点和特点,是我们下面重点学习的地方!

  DefaultAdvisorAutoProxyCreator支持beanName具有给定前缀的通知器bean才能够算作候选Advisor通知器。它提供了advisorBeanNamePrefix属性用来手动设置前缀:

@Nullable
private String advisorBeanNamePrefix;

/**
 * 设置Advisor通知器 beanName 的前缀
 */
public void setAdvisorBeanNamePrefix(@Nullable String advisorBeanNamePrefix) {
    this.advisorBeanNamePrefix = advisorBeanNamePrefix;
}

/**
 * 获取Advisor通知器 beanName 的前缀
 */
@Nullable
public String getAdvisorBeanNamePrefix() {
    return this.advisorBeanNamePrefix;
}

  DefaultAdvisorAutoProxyCreator还实现了BeanNameAware接口,容器中的DefaultAdvisorAutoProxyCreator在实例化完毕之后的initializeBean初始化方法中,首先就会调用BeanNameAware接口的setBeanName方法,并将当前DefaultAdvisorAutoProxyCreator的beanName传递到方法参数中!
  DefaultAdvisorAutoProxyCreator的setBeanName方法实现如下,它的目的就是在没有配置advisorBeanNamePrefix的时候,设置默认的前缀为beanName+"."

/**
 * 默认的前缀的点
 */
public static final String SEPARATOR = ".";

/**
 * bean实例创建完毕之后自动回调的方法,将当前创建的bean的beanName传递进来
 * 
 */
@Override
public void setBeanName(String name) {
    //如果未设置Advisor通知器 beanName 的前缀,那么使用beanName+"."作为默认前缀
    if (this.advisorBeanNamePrefix == null) {
        this.advisorBeanNamePrefix = name + SEPARATOR;
    }
}

  当然,我们也可以通过usePrefix属性手动控制是否开启前缀匹配,默认不启用,即所有的Advisor都是候选Advisor。

/**
 * 是否启用前缀匹配的标志,默认不启用,即所有的Advisor都是候选Advisor
 */
private boolean usePrefix = false;

/**
 * 设置启用标志
 */
public void setUsePrefix(boolean usePrefix) {
    this.usePrefix = usePrefix;
}

/**
 * 获取启用标志
 */
public boolean isUsePrefix() {
    return this.usePrefix;
}

  最后就是我们的isEligibleAdvisorBean方法了,它也非常的简单,用于判断是否是合格的候选AdvisorBean。如果启用前缀匹配,那么通过beanName匹配前缀,否则默认返回true。

/**
 * 判断是否是合格的候选AdvisorBean
 * <p>
 * 如果启用前缀匹配,那么beanName匹配前缀,否则默认返回true
 *
 * @param beanName 某个Advisor的beanName
 */
@Override
protected boolean isEligibleAdvisorBean(String beanName) {
    //如果没有启用前缀匹配,那么直接返回true,表示合格
    if (!isUsePrefix()) {
        return true;
    }
    //那么如果prefix不为null并且当前Advisor的beanName以指定的前缀开始,那么说明合格,否则返回false
    String prefix = getAdvisorBeanNamePrefix();
    return (prefix != null && beanName.startsWith(prefix));
}

  是的,DefaultAdvisorAutoProxyCreator介绍完了,它就是这么简单……当然这里的“简单”是建立在我们已经熟悉了至少是AspectJAwareAdvisorAutoProxyCreator自动代理创建者的源码之后,而AspectJAwareAdvisorAutoProxyCreator的源码我们此前就讲过了!

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!


喜欢 (0)