AspectJAwareAdvisorAutoProxyCreator 的类图

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

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初始化前后添加一些自己的逻辑。

1     @Nullable
2 default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
3 return bean;
4 }
5
6 @Nullable
7 default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
8 return bean;
9 }

  InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,它额外增加了3个新的方法:postProcessBeforeInstantiation( 目标对象被实例化之前调用的方法,可以返回目标实例的一个代理用来代替目标实例 )、postProcessAfterInstantiation(该方法在Bean实例化之后执行,返回false,会忽略属性值的设置;如果返回true,会按照正常流程设置属性值) 和 postProcessPropertyValues(对属性值进行修改,未来版本将会删除)。

 1     @Nullable
2 default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
3 return null;
4 }
5
6 default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
7 return true;
8 }
9
10 @Nullable
11 default PropertyValues postProcessPropertyValues(
12 PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
13
14 return pvs;
15 }

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

 1     @Nullable
2 default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
3 return null;
4 }
5
6 @Nullable
7 default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
8 return null;
9 }
10
11 default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
12 return bean;
13 }

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

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

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

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

 1     @Override
2 @SuppressWarnings("unchecked")
3 protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
4 List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
5 for (Advisor element : advisors) {
6 partiallyComparableAdvisors.add(
7 new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
8 }
9 List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
10 if (sorted != null) {
11 List<Advisor> result = new ArrayList<>(advisors.size());
12 for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
13 result.add(pcAdvisor.getAdvisor());
14 }
15 return result;
16 }
17 else {
18 return super.sortAdvisors(advisors);
19 }
20 }

  在增强链头部增加一个ExposeInvocationInterceptor,使用AspectJ表达式切入点和使用AspectJ样式的advisor时,需要这些附加advisor。

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

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

 1     @Override
2 protected boolean shouldSkip(Class<?> beanClass, String beanName) {
3 // TODO: Consider optimization by caching the list of the aspect names
4 List<Advisor> candidateAdvisors = findCandidateAdvisors();
5 for (Advisor advisor : candidateAdvisors) {
6 if (advisor instanceof AspectJPointcutAdvisor &&
7 ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
8 return true;
9 }
10 }
11 return super.shouldSkip(beanClass, beanName);
12 }

  AspectJAwareAdvisorAutoProxyCreator 还有一个子类叫 AnnotationAwareAspectJAutoProxyCreator,子类AnnotationAwareAspectJAutoProxyCreator是用于处理当前应用程序上下文中的所有AspectJ注释方面以及Spring Advisor。如果Spring AOP的基于代理的模型能够应用任何AspectJ注释的类,它们的advisor将被自动识别,这涵盖了方法执行连接点,Spring Advisor的处理遵循AbstractAdvisorAutoProxyCreator中建立的规则。

生成代理对象

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

 1     @Override
2 public void init() {
3 // In 2.0 XSD as well as in 2.1 XSD.
4 registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
5 registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
6 registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
7
8 // Only in 2.0 XSD: moved to context namespace as of 2.1
9 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
10 }
  • <aop:config>方式使用 AspectJAwareAdvisorAutoProxyCreator 创建代理

  • <aop:aspectj-autoproxy>使用 AnnotationAwareAspectJAutoProxyCreator 创建代理

ConfigBeanDefinitionParser.java

 1     @Override
2 @Nullable
3 public BeanDefinition parse(Element element, ParserContext parserContext) {
4 CompositeComponentDefinition compositeDef =
5 new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
6 parserContext.pushContainingComponent(compositeDef);
7
8 configureAutoProxyCreator(parserContext, element); // 注册AspectJAwareAdvisorAutoProxyCreator
9
10 List<Element> childElts = DomUtils.getChildElements(element);
11 for (Element elt: childElts) {
12 String localName = parserContext.getDelegate().getLocalName(elt);
13 if (POINTCUT.equals(localName)) {
14 parsePointcut(elt, parserContext);
15 }
16 else if (ADVISOR.equals(localName)) {
17 parseAdvisor(elt, parserContext);
18 }
19 else if (ASPECT.equals(localName)) {
20 parseAspect(elt, parserContext);
21 }
22 }
23
24 parserContext.popAndRegisterContainingComponent();
25 return null;
26 }
27
28 private void configureAutoProxyCreator(ParserContext parserContext, Element element) {
29 AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
30 }

AopConfigUtils.java

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

  AspectJAwareAdvisorAutoProxyCreator 实现了 BeanPostProcessor 等上面介绍的接口,主要作用于Bean初始化前后,实例化前后,所有的Bean都被作用到。InstantiationAwareBeanPostProcessor 是 BeanPostProcessor的子接口,但它的调用时间点发生在Bean实例化前,在真正调用doCreateBean()创建bean实例之前执行postProcessBeforeInstantiation()。

AbstractAutoProxyCreator.java

 1     @Override
2 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
3 Object cacheKey = getCacheKey(beanClass, beanName);  // 得到一个缓存的唯一key(根据beanClass和beanName生成唯一key)
4      // 如果当前targetSourcedBeans(通过自定义TargetSourceCreator创建的TargetSource)不包含cacheKey
5 if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
6 if (this.advisedBeans.containsKey(cacheKey)) {  //advisedBeans(已经被增强的Bean,即AOP代理对象)中包含当前cacheKey,返回null,即走Spring默认流程
7 return null;
8 }
9 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {// 如果是基础设施类(如Advisor、Advice、AopInfrastructureBean的实现)不进行处理;(略)
10 this.advisedBeans.put(cacheKey, Boolean.FALSE);
11 return null;
12 }
13 }
14
15 // 如果有自定义的TargetSource,在此处创建代理
16 // 禁止目标Bean的不必要的默认实例化:
17 // TargetSource将以自定义方式处理目标实例。
18 TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
19 if (targetSource != null) {
20 if (StringUtils.hasLength(beanName)) {
21 this.targetSourcedBeans.add(beanName);
22 }
23 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
24 Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
25 this.proxyTypes.put(cacheKey, proxy.getClass());
26 return proxy;
27 }
28
29 return null;
30 }

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

 1     @Override
2 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
3 if (bean != null) {
4 Object cacheKey = getCacheKey(bean.getClass(), beanName);
5 if (!this.earlyProxyReferences.contains(cacheKey)) {  // 如果之前调用过getEarlyBeanReference获取包装目标对象到AOP代理对象(如果需要),则不再执行
6 return wrapIfNecessary(bean, beanName, cacheKey);  // 包装目标对象到AOP代理对象(如果需要)
7 }
8 }
9 return bean;
10 }
11
12 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
13 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { // 通过TargetSourceCreator进行自定义TargetSource不需要包装
14 return bean;
15 }
16 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {  // 不应该被增强对象不需要包装
17 return bean;
18 }
19 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { // 基础设施或应该skip的不需要保证
20 this.advisedBeans.put(cacheKey, Boolean.FALSE);
21 return bean;
22 }
23
24 // 如果有advise则创建代理。
25 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
26 if (specificInterceptors != DO_NOT_PROXY) {
27 this.advisedBeans.put(cacheKey, Boolean.TRUE);
28 Object proxy = createProxy(
29 bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // 创建代理对象
30 this.proxyTypes.put(cacheKey, proxy.getClass());
31 return proxy;
32 }
33
34 this.advisedBeans.put(cacheKey, Boolean.FALSE);
35 return bean;
36 }

参考:

Spring内部的BeanPostProcessor接口总结

【Spring源码分析】AOP源码解析(下篇)

AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍的更多相关文章

  1. AOP源码解析之二-创建AOP代理前传,获取AOP信息

    AOP源码解析之二-创建AOP代理前传,获取AOP信息. 上篇文章对AOP的基本概念说清楚了,那么接下来的AOP还剩下两个大的步骤获取定义的AOP信息,生成代理对象扔到beanFactory中. 本篇 ...

  2. 老生常谈系列之Aop--Spring Aop源码解析(二)

    老生常谈系列之Aop--Spring Aop源码解析(二) 前言 上一篇文章老生常谈系列之Aop--Spring Aop源码解析(一)已经介绍完Spring Aop获取advice切面增强方法的逻辑, ...

  3. 老生常谈系列之Aop--Spring Aop源码解析(一)

    老生常谈系列之Aop--Spring Aop源码解析(一) 前言 上一篇文章老生常谈系列之Aop--Spring Aop原理浅析大概阐述了动态代理的相关知识,并且最后的图给了一个Spring Aop实 ...

  4. 【Spring源码分析】AOP源码解析(上篇)

    前言 前面写了六篇文章详细地分析了Spring Bean加载流程,这部分完了之后就要进入一个比较困难的部分了,就是AOP的实现原理分析.为了探究AOP实现原理,首先定义几个类,一个Dao接口: pub ...

  5. 第四章 dubbo内核之aop源码解析

    ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); final P ...

  6. Spring系列(五):Spring AOP源码解析

    一.@EnableAspectJAutoProxy注解 在主配置类中添加@EnableAspectJAutoProxy注解,开启aop支持,那么@EnableAspectJAutoProxy到底做了什 ...

  7. [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析

    String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识,  ...

  8. Spring源码解析——核心类介绍

    前言: Spring用了这么久,虽然Spring的两大核心:IOC和AOP一直在用,但是始终没有搞懂Spring内部是怎么去实现的,于是决定撸一把Spring源码,前前后后也看了有两边,很多东西看了就 ...

  9. AOP源码解析:AspectJExpressionPointcutAdvisor类

    先看看 AspectJExpressionPointcutAdvisor 的类图 再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名 1 pa ...

随机推荐

  1. [第十四篇]——Docker Machine之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker Machine 简介 Docker Machine 是一种可以让您在虚拟主机上安装 Docker 的工具,并可以使用 docker-machine 命令来管理主机. Docker Mac ...

  2. springboot:@ConditionalOnProperty根据不同时机注入不同实现的bean

    一.引言 在开发中经常会碰到这样的情形,一个接口会有不同的实现,但在开发中都是基于接口的注入,那么怎么根据不同的需求注入不同的类型就是一个值得考虑的问题.在注入属性时常用的两个注解是@Autowire ...

  3. Docker系列(24)- 实战:DockerFile制作tomcat镜像

    实战:DockerFile制作tomcat镜像 step-1 准备镜像文件 tomcat压缩包,jdk压缩包! step-2 编写dockerfile文件,官方命名Dockerfile,build会自 ...

  4. Linux系列(21) - 光盘、U盘挂载

    挂载光盘 mount命令.umount命令 step-1 建立挂载点 原理:相当于建立盘符,建个目录读取光盘内容 命令:[root@localhost ~]# mkdir /mnt/cdrom/ 备注 ...

  5. javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题

    * 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...

  6. Python创建Excel表格,Word并写入数据

    from tkinter import Tk from time import sleep from tkinter.messagebox import showwarning import win3 ...

  7. Gitee自动化部署python脚本

    一.前期准备 1.1 安装环境 1.安装python3 2.打开命令行安装selenium pip install selenium 二.python代码 2.1 源码 #!/usr/bin/pyth ...

  8. 浅谈语音质量保障:如何测试 RTC 中的音频质量?

    日常音视频开会中我们或多或少会遭遇这些场景:"喂喂喂,可以听到我说话吗?我听你的声音断断续续的","咦,我怎么可以听到回声?","太吵啦,我听不清楚你 ...

  9. 鸿蒙内核源码分析(管道文件篇) | 如何降低数据流动成本 | 百篇博客分析OpenHarmony源码 | v70.01

    百篇博客系列篇.本篇为: v70.xx 鸿蒙内核源码分析(管道文件篇) | 如何降低数据流动成本 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说一 ...

  10. Python 文件路径设置

    菜鸟教程:https://www.runoob.com/python/os-chdir.html Python官方文件教程:https://docs.python.org/3.9/library/os ...