欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > Spring-Aop源码解析

Spring-Aop源码解析

2024/11/30 9:37:20 来源:https://blog.csdn.net/qq_37200262/article/details/140108930  浏览:    关键词:Spring-Aop源码解析

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@Nullablepublic 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:aspectList<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这里再执行会去取缓存
在这里插入图片描述
判断对象是否要被拦截执行生成代理对象,这一步判断切点表达式的匹配
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com