乐趣区

关于spring:Spring-AOP核心类解析这是最全的一篇了

写在后面

最近,不少小伙伴在催更【Spring 注解驱动开发】专题,好吧,【Spring 注解驱动开发】专题的确有很长时间没更新了。那咱们从明天开始更新【Spring 注解驱动开发】专题,同样的,咱们还是以源码解析为主。

文章已同步收录到:https://github.com/sunshinelyz/technology-binghe 和 https://gitee.com/binghe001/technology-binghe。如果文件对你有点帮忙,别忘记给个 Star 哦!

关注【冰河技术】微信公众号,回复“Spring 注解”支付工程源码。

类结构图

咱们先来看下 AnnotationAwareAspectJAutoProxyCreator 类的结构图。

上图中一些 类 / 接口 的介绍:

AspectJAwareAdvisorAutoProxyCreator : 公开了 AspectJ 的调用上下文,并弄清楚来自同所有面的多个 Advisor 在 AspectJ 中的优先级规定。

AbstractAdvisorAutoProxyCreator : 通用主动代理创立器,它基于检测到的每个参谋程序为特定 bean 构建 AOP 代理。

AbstractAutoProxyCreator : 扩大了 ProxyProcessorSupport,实现了 SmartInstantiationAwareBeanPostProcessor、BeanFactoryAware 接口,是 BeanPostProcessor 实现,该实现应用 AOP 代理包装每个合格的 bean,并在调用 bean 自身之前委派给指定的拦截器。

BeanFactoryAware : 实现了该接口的 Bean 能够晓得它属于那个 BeanFactory,Bean 能够通过 Spring 容器查找它的协同者(依赖查找),但大多数的 Bean 是通过结构器参数和 Bean 办法(依赖注入)来获取它的协同者。

BeanPostProcessor:工厂钩子,容许自定义批改新的 bean 实例。例如,查看标记接口或应用代理包装 bean。如果咱们须要在 Spring 容器中实现 Bean 的实例化,配置和其初始化前后增加一些本人的逻辑解决,咱们就能够定义一个或多个 BeanPostProcessor 接口的实现,而后注册到容器中。

InstantiationAwareBeanPostProcessor : BeanPostProcessor 的子接口,它增加了实例化之前的回调,以及实例化之后但设置了显式属性或主动拆卸之前的回调。它外部提供了 3 个办法,再加上 BeanPostProcessor 接口外部的 2 个办法,实现这个接口须要实现 5 个办法。InstantiationAwareBeanPostProcessor 接口的次要作用在于指标对象的实例化过程中须要解决的事件,包含实例化对象的前后过程以及实例的属性设置。

SmartInstantiationAwareBeanPostProcessor : InstantiationAwareBeanPostProcessor 接口的扩大,多出了 3 个办法,增加了用于预测已解决 bean 的最终类型的回调,再加上父接口的 5 个办法,所以实现这个接口须要实现 8 个办法,次要作用也是在于指标对象的实例化过程中须要解决的事件。

总之:AspectJAwareAdvisorAutoProxyCreator 为 AspectJ 切面类创立主动代理。

外围类解析

BeanPostProcessor 接口中的两个办法 postProcessBeforeInitialization 和 postProcessAfterInitialization,作用是对 Bean 初始化前后 增加一些本人的逻辑。

@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}

@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}

InstantiationAwareBeanPostProcessorBeanPostProcessor 的子接口,它额定减少了 3 个新的办法:postProcessBeforeInstantiation(指标对象被 实例化之前 调用的办法,能够返回指标实例的一个代理用来代替指标实例)、postProcessAfterInstantiation(该办法在 Bean实例化之后 执行,返回 false,会疏忽属性值的设置;如果返回 true,会依照失常流程设置属性值)和 postProcessPropertyValues(对属性值进行批改,将来版本将会删除)

@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}

default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}

@Nullable
default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}

SmartInstantiationAwareBeanPostProcessor接口继承 InstantiationAwareBeanPostProcessor 接口,外面定义了 3 个办法:predictBeanType(预测 Bean 的类型)、determineCandidateConstructors(抉择适合的结构器)、getEarlyBeanReference(解决循环援用问题)。

@Nullable
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {return null;}

@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {return null;}

default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}

AbstractAutoProxyCreator 是 AOP 的一个外围类,它实现了 SmartInstantiationAwareBeanPostProcessor、BeanFactoryAware 接口,实现了代理创立的逻辑,应用 AOP 代理包装每个合格的 bean,并在调用 bean 自身之前委派给指定的拦截器。

AbstractAdvisorAutoProxyCreator 通用主动代理创立器,它基于检测每个 bean 的增强器,为非凡的 bean 构建 AOP 代理。子类能够重写此 findCandidateAdvisors()办法,以返回实用于任何对象的 advisor 的自定义列表,子类还能够重写继承的 AbstractAutoProxyCreator.shouldSkip()办法,以将某些对象排除在主动代理之外。

protected List<Advisor> findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
     return this.advisorRetrievalHelper.findAdvisorBeans();}

AspectJAwareAdvisorAutoProxyCreator 扩大 AbstractAdvisorAutoProxyCreator,公开了 AspectJ 的调用上下文,并在多个增强器来自同所有面时搞清楚 AspectJ 的倡议优先级程序。按 AspectJ 优先级排序其余部分:

@Override
@SuppressWarnings("unchecked")
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
    for (Advisor element : advisors) {
        partiallyComparableAdvisors.add(new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
    }
    List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
    if (sorted != null) {List<Advisor> result = new ArrayList<>(advisors.size());
        for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {result.add(pcAdvisor.getAdvisor());
        }
        return result;
    }
    else {return super.sortAdvisors(advisors);
    }
}

在加强链头部减少一个 ExposeInvocationInterceptor,应用 AspectJ 表达式切入点和应用 AspectJ 款式的 advisor 时,须要这些附加 advisor。

protected void extendAdvisors(List<Advisor> candidateAdvisors) {AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}

如果尔后处理器不应该思考将给定的 bean 用于主动代理,子类应重写此办法以返回 true

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // TODO: Consider optimization by caching the list of the aspect names
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {return true;}
    }
    return super.shouldSkip(beanClass, beanName);
}

AspectJAwareAdvisorAutoProxyCreator 还有一个子类叫 AnnotationAwareAspectJAutoProxyCreator,子类 AnnotationAwareAspectJAutoProxyCreator 是用于解决以后应用程序上下文中的所有 AspectJ 正文方面以及 Spring Advisor。如果 Spring AOP 的基于代理的模型可能利用任何 AspectJ 正文的类,它们的 advisor 将被自动识别,这涵盖了办法执行连接点,Spring Advisor 的解决遵循 AbstractAdvisorAutoProxyCreator 中建设的规定。

生成代理对象

从应用 <aop:xxx> 标签来主动生成代理的话,先看看 AopNamespaceHandler,应用 <aop:config> 标签则应用 ConfigBeanDefinitionParser 解析,应用了 <aop:aspectj-autoproxy> 标签则应用 AspectJAutoProxyBeanDefinitionParser 解析,顺次类推。

@Override
public void init() {
    // In 2.0 XSD as well as in 2.1 XSD.
    registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
    registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
    registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

    // Only in 2.0 XSD: moved to context namespace as of 2.1
    registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
  • <aop:config> 形式应用 AspectJAwareAdvisorAutoProxyCreator 创立代理
  • <aop:aspectj-autoproxy> 应用 AnnotationAwareAspectJAutoProxyCreator 创立代理

ConfigBeanDefinitionParser.java

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    CompositeComponentDefinition compositeDef =
        new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
    parserContext.pushContainingComponent(compositeDef);

    configureAutoProxyCreator(parserContext, element); // 注册 AspectJAwareAdvisorAutoProxyCreator

    List<Element> childElts = DomUtils.getChildElements(element);
    for (Element elt: childElts) {String localName = parserContext.getDelegate().getLocalName(elt);
        if (POINTCUT.equals(localName)) {parsePointcut(elt, parserContext);
        }
        else if (ADVISOR.equals(localName)) {parseAdvisor(elt, parserContext);
        }
        else if (ASPECT.equals(localName)) {parseAspect(elt, parserContext);
        }
    }

    parserContext.popAndRegisterContainingComponent();
    return null;
}

private void configureAutoProxyCreator(ParserContext parserContext, Element element) {AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}

AopConfigUtils.java

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
    CompositeComponentDefinition compositeDef =
        new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
    parserContext.pushContainingComponent(compositeDef);

    configureAutoProxyCreator(parserContext, element); // 注册 AspectJAwareAdvisorAutoProxyCreator

    List<Element> childElts = DomUtils.getChildElements(element);
    for (Element elt: childElts) {String localName = parserContext.getDelegate().getLocalName(elt);
        if (POINTCUT.equals(localName)) {parsePointcut(elt, parserContext);
        }
        else if (ADVISOR.equals(localName)) {parseAdvisor(elt, parserContext);
        }
        else if (ASPECT.equals(localName)) {parseAspect(elt, parserContext);
        }
    }

    parserContext.popAndRegisterContainingComponent();
    return null;
}

private void configureAutoProxyCreator(ParserContext parserContext, Element element) {AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
}

AopConfigUtils.java

public static void registerAspectJAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
    // 在这里注册的是 AspectJAwareAdvisorAutoProxyCreator
    BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
    useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
    registerComponentIfNecessary(beanDefinition, parserContext); // 注册组件
}
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}

AspectJAwareAdvisorAutoProxyCreator 实现了 BeanPostProcessor 等下面介绍的接口,次要作用于 Bean 初始化前后,实例化前后,所有的 Bean 都被作用到。InstantiationAwareBeanPostProcessorBeanPostProcessor的子接口,但它的调用工夫点产生在 Bean 实例化前,在真正调用 doCreateBean()创立 bean 实例之前执行 postProcessBeforeInstantiation()。

AbstractAutoProxyCreator.java

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {Object cacheKey = getCacheKey(beanClass, beanName);  // 失去一个缓存的惟一 key(依据 beanClass 和 beanName 生成惟一 key)// 如果以后 targetSourcedBeans(通过自定义 TargetSourceCreator 创立的 TargetSource)不蕴含 cacheKey
    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {if (this.advisedBeans.containsKey(cacheKey)) {  //advisedBeans(曾经被加强的 Bean,即 AOP 代理对象)中蕴含以后 cacheKey,返回 null,即走 Spring 默认流程
            return null;
        }
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {// 如果是基础设施类(如 Advisor、Advice、AopInfrastructureBean 的实现)不进行解决;(略)this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }

    // 如果有自定义的 TargetSource,在此处创立代理
    // 禁止指标 Bean 的不必要的默认实例化:// TargetSource 将以自定义形式解决指标实例。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;
}

通过 AbstractAutoProxyCreator 中的 postProcessAfterInitialization() 创立 AOP 代理。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {  // 如果之前调用过 getEarlyBeanReference 获取包装指标对象到 AOP 代理对象(如果须要),则不再执行
            return wrapIfNecessary(bean, beanName, cacheKey);  // 包装指标对象到 AOP 代理对象(如果须要)}
    }
    return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { // 通过 TargetSourceCreator 进行自定义 TargetSource 不须要包装
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {  // 不应该被加强对象不须要包装
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { // 基础设施或应该 skip 的不须要保障
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 如果有 advise 则创立代理。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;
}

好了,明天就到这儿吧,我是冰河,咱们下期见~~

重磅福利

微信搜一搜【冰河技术】微信公众号,关注这个有深度的程序员,每天浏览超硬核技术干货,公众号内回复【PDF】有我筹备的一线大厂面试材料和我原创的超硬核 PDF 技术文档,以及我为大家精心筹备的多套简历模板(不断更新中),心愿大家都能找到心仪的工作,学习是一条时而郁郁寡欢,时而开怀大笑的路,加油。如果你通过致力胜利进入到了心仪的公司,肯定不要懈怠放松,职场成长和新技术学习一样,逆水行舟。如果有幸咱们江湖再见!

另外,我开源的各个 PDF,后续我都会继续更新和保护,感激大家长期以来对冰河的反对!!

退出移动版