Spring-Aop源码解析

本文主要讲解spring实现aop的相关源码学习教程,以aop.xml配置文件的方式为例,讲解如何将配置文件的标签解析成bean定义信息,存放到beanfactory中。以及advisor的bean定义信息以及实例化的过程;对哪些类进行代理,以及判断依据是什么。。。。。。

1.实现aop用配置文件的方式配置如下:

    <bean id="logUtil" class="com.mashibing.aop.xml.util.LogUtil" ></bean>
    <bean id="myCalculator" class="com.mashibing.aop.xml.service.MyCalculator" ></bean>
    <aop:config>
        <aop:aspect ref="logUtil">
            <aop:pointcut id="myPoint" expression="execution( Integer com.mashibing.aop.xml.service.MyCalculator.*  (..))"/>
            <aop:around method="around" pointcut-ref="myPoint"></aop:around>
            <aop:before method="start" pointcut-ref="myPoint"></aop:before>
            <aop:after method="logFinally" pointcut-ref="myPoint"></aop:after>
            <aop:after-returning method="stop" pointcut-ref="myPoint" returning="result"></aop:after-returning>
            <aop:after-throwing method="logException" pointcut-ref="myPoint" throwing="e"></aop:after-throwing>
        </aop:aspect>
    </aop:config>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

2.接下来开始配置文件标签的解析:
真正解析关键在这个方法里

parse:108, ConfigBeanDefinitionParser (org.springframework.aop.config)
	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		CompositeComponentDefinition compositeDef =
				new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
		parserContext.pushContainingComponent(compositeDef);
		// 注册自动代理模式创建器,AspectjAwareAdvisorAutoProxyCreator 
		configureAutoProxyCreator(parserContext, element);
		// 解析aop:config子节点下的aop:pointcut/aop:advice/aop:aspect
		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;
	}

configureAutoProxyCreator(parserContext, element);方法最终执行到registerOrEscalateApcAsRequired:145, AopConfigUtils (org.springframework.aop.config)
执行registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);创建AUTO_PROXY_CREATOR_BEAN_NAME的RootBeanDefinition即这个内部类的bean定义信息加载,后续创建对象org.springframework.aop.config.internalAutoProxyCreator

解析aop:config子节点下的aop:pointcut/aop:advice/aop:aspect

在这里插入图片描述
整个方法的调用执行链路
在这里插入图片描述

parseAspect(elt, parserContext);

这个方法用来解析xml配置文件,生成bean定义信息,方便后续的实例化初始化创建代理对象的操作。advisor内部有advice,创建advice内部有三个属性。
在这里插入图片描述
对xml文件解析为bean定义信息之后beanMap里新增如下:
在这里插入图片描述
对xml文件解析为bean定义信息之后开始实例化,链路如下:
在这里插入图片描述

给BeanPostProcessors一个机会来返回代理来替代真正的实例,应用实例化前的前置处理器,用户自定义动态代理的方式,针对于当前的被代理类需要经过标准的代理流程来创建对象

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

实例化的前置处理

postProcessBeforeInstantiation:262, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)

isInfrastructureClass:判断bean的类型是不是内部的类型,
比如Advice,Pointcut,Advisor,AopInfrastructureBean这些是跟AOP相关的,所以不应该被处理
shouldSkip:是否跳过

if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) 

findAdvisorBeans:81,BeanFactoryAdvisorRetrievalHelper(org.springframework.aop.framework.autoproxy)
这个方法获取当前BeanFactory中所有实现了Advisor接口的bean的名称然后进行实例化生成bean对象放到缓存中
在这里插入图片描述
从spring中获取 bean class 对应的 bean,将其放入advisors中:org.springframework.aop.aspectj.AspectJPointcutAdvisor#0
在这里插入图片描述

advisors.add(this.beanFactory.getBean(name, Advisor.class));

这个方法实例化生成advisor,前面说过advisor有advice,advice有三个对象,因此要先生成advice需要的三个对象,advisor属性constructorArgumentValues可以看到有
Root bean: class [org.springframework.aop.aspectj.AspectJAroundAdvice]; scope=; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null AspectJAroundAdvice的属性constructorArgumentValues可以看到有下面三个:这三个实例化需要用无参构造,advice和advisor用有参构造。点进去可以看到除了advice依赖的这三个 其余均有有参构造函数。
在这里插入图片描述

这个操作是实例化生成所有advisor对象,包括解析的xml文件的配置以及注解实现的切面方式。
在这里插入图片描述

findAdvisorBeans:102, BeanFactoryAdvisorRetrievalHelper (org.springframework.aop.framework.autoproxy)
findCandidateAdvisors:131, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
findCandidateAdvisors:100, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
shouldSkip:110, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
postProcessBeforeInstantiation:262, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsBeforeInstantiation:1396, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
resolveBeforeInstantiation:1365, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)这个方法是用户自定义实现动态代理,这里只生成advisor对象放缓存 不生成代理对象
createBean:618, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:417, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 71399214 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$12)
getSingleton:370, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:414, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:260, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:993, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:1024, AbstractApplicationContext (org.springframework.context.support)
refresh:614, AbstractApplicationContext (org.springframework.context.support)
<init>:150, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:87, ClassPathXmlApplicationContext (org.springframework.context.support)
main:15, TestAop (com.mashibing.aop.xml)

advisor对象在一级缓存中存储。
在这里插入图片描述

postProcessBeforeInstantiation:274, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)

targetSource这里为空 则不会进入后续创建代理方法。
在这里插入图片描述

resolveBeforeInstantiation:1365, AbstractAutowireCapableBeanFactory这里没有生成代理对象,后续方法会继续生成:

resolveBeforeInstantiation已经执行过最上面的部分,shouldskip实例化advisor这里再执行会去取缓存
在这里插入图片描述
判断对象是否要被拦截执行生成代理对象,这一步判断切点表达式的匹配
在这里插入图片描述
匹配成功
// 获取当前bean的Advices和Advisors Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
specificInterceptors 不为空则执行createProxy方法创建代理对象。

相关推荐

  1. spring管理bean

    2024-07-12 22:28:02       21 阅读
  2. Redis AOF

    2024-07-12 22:28:02       62 阅读
  3. spring oauth2 authorization server 配置

    2024-07-12 22:28:02       53 阅读
  4. redisson-spring-boot-starter 自动化配置

    2024-07-12 22:28:02       47 阅读
  5. spring-orm:6 HibernateJpaVendorAdapter

    2024-07-12 22:28:02       49 阅读
  6. Spring之Bean生命周期

    2024-07-12 22:28:02       40 阅读
  7. Spring之事务底层

    2024-07-12 22:28:02       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 22:28:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 22:28:02       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 22:28:02       58 阅读
  4. Python语言-面向对象

    2024-07-12 22:28:02       69 阅读

热门阅读

  1. 计算机网络 5.6网桥与交换机

    2024-07-12 22:28:02       15 阅读
  2. 安全开发--多语言基础知识

    2024-07-12 22:28:02       18 阅读
  3. Requests库如何用于发送HTTP请求

    2024-07-12 22:28:02       24 阅读
  4. Spring MVC中Restful风格引入

    2024-07-12 22:28:02       18 阅读
  5. 【25届秋招备战C++】算法篇-排序算法合集

    2024-07-12 22:28:02       18 阅读
  6. 国道省道乡道见闻

    2024-07-12 22:28:02       21 阅读
  7. 解锁深度学习黑箱:注意力机制的神秘力量

    2024-07-12 22:28:02       21 阅读
  8. LLM生成nvidia-h100-tensor-core-hopper-whitepaper.pdf摘要

    2024-07-12 22:28:02       19 阅读
  9. 介绍一下Feed流

    2024-07-12 22:28:02       19 阅读
  10. Influxdb v2.x的基本概念

    2024-07-12 22:28:02       19 阅读