Spring 事务源码(三):事务相关对象的创建
1、PropertySourcesPlaceholderConfigurer 创建占位符处理的bean
1 public static void invokeBeanFactoryPostProcessors( 2 ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { 3 4 // 将已经执行过的BFPP存储在processedBeans中,防止重复执行 5 Set<String> processedBeans = new HashSet<>(); 6 7 // 找到所有实现BeanFactoryPostProcessor接口的类 8 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); 9 10 // 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor 11 List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); 12 13 // 遍历postProcessorNames,将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开 14 for (String ppName : postProcessorNames) { 15 // 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor到priorityOrderedPostProcessors 16 // 此处通过 getBean->doGetBean->createBean->DoCreateBean创建PropertySourcesPlaceholderConfigurer对象 17 priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); 18 } 19 20 // 对实现了PriorityOrdered接口的BeanFactoryPostProcessor进行排序 21 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); 22 23 // 遍历实现了PriorityOrdered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法 24 // 对于 PropertySourcesPlaceholderConfigurer 来说,是遍历每一个beanDefinition中的占位符 25 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); 26 37 }
2、AspectJAwareAdvisorAutoProxyCreator 创建自动动态代理创建器bean
AspectJAwareAdvisorAutoProxyCreator实现了BeanPostProcessor接口,在IOC容器刷新过程中,registerBeanPostProcessors(beanFactory)方法处理实现BeanPostProcessor接口的bean,创建详情在AOP源码(三):创建AOP相关的Bean中有描述,此处不再赘述。
3、AspectJExpressionPointcutAdvisor 创建事务通知Advisor

在AOP源码(三):创建AOP相关的Bean中提到Advisor的创建是在创建首个普通bean标签的对象实例化之前处理的,本次案例中就是在创建dataSource实例化之前处理的,即AbstractAutowireCapableBeanFactory#createBean-》AbstractAutowireCapableBeanFactoryresolveBeforeInstantiation处理的。
在事务源码(二):beanDefinition的准备-配置文件加载中提到pointcut-ref、advice-ref被设置在Advisor的beanDefinition的propertyValues属性中,而propertyValues中内容是在bean实例化完成之后,完成bean属性填充时需要用到,按照这个思路看看Advisor在属性填充做了什么事情?
1 // 填充属性 2 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { 3 4 //如果mdb有PropertyValues就获取其PropertyValues 5 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); 6 7 //如果pvs不为null 8 if (pvs != null) { 9 //应用给定的属性值,解决任何在这个bean工厂运行时其他bean的引用 (RuntimeBeanReference) 10 applyPropertyValues(beanName, mbd, bw, pvs); 11 } 12 }
1、Advisor属性填充核心流程图
2、Advisor属性填充核心伪代码
1 // 解析Value 2 public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { 3 4 // 如果value是RuntimeBeanReference实例,创建bean对象并返回 5 if (value instanceof RuntimeBeanReference) { 6 //将value强转成RuntimeBeanReference对象 7 RuntimeBeanReference ref = (RuntimeBeanReference) value; 8 //解析出对应ref所封装的Bean元信息(即Bean名,Bean类型)的Bean对象: 9 return resolveReference(argName, ref); 10 } 11 12 // 如果value是RuntimeBeanNameReference实例,获取引用的Bean名称字符串 13 else if (value instanceof RuntimeBeanNameReference) { 14 //从value中获取引用的Bean名 15 String refName = ((RuntimeBeanNameReference) value).getBeanName(); 16 //对refName进行解析,然后重新赋值给refName 17 refName = String.valueOf(doEvaluate(refName)); 18 19 //返回经过解析且经过检查其是否存在于Bean工厂的引用Bean名【refName】 20 return refName; 21 } 22 23 }
AspectJExpressionPointcutAdvisor创建完成,在缓存singletonObject查看创建详情,pointcut属性已填充完成,但advice属性确为null。在上面的分析中,propertyValues中key为adviceBeanName的value为RuntimeBeanNameReference类型,只返回了advice-ref的属性值myAdvice,并未对创建Advice相关的bean。
那么Advice是在哪里创建的呢?
4、TransactionInterceptor 创建事务通知Advice
4.1、Advice创建核心流程图
4.2、Advice创建
1、创建Advice的时机
1 // 拓展通知-> 添加 ExposeInvocationInterceptor、TransactionIntercecptor 2 protected void extendAdvisors(List<Advisor> candidateAdvisors) { 3 AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors); 4 }
1 // 获取事务执行链 2 public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) { 3 4 // advisors通知器如果为空,则说明不需要代理 5 if (!advisors.isEmpty()) { 6 // 判断是否为Before/After/Around/AfterReturning/AfterThrowing等通知 7 boolean foundAspectJAdvice = false; 8 for (Advisor advisor : advisors) { 9 // 判断Advisor中是否包含Advice 10 if (isAspectJAdvice(advisor)) { 11 foundAspectJAdvice = true; 12 break; 13 } 14 } 15 // advisors中包含Advice,并且不包含ExposeInvocationInterceptor,添加 16 if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) { 17 advisors.add(0, ExposeInvocationInterceptor.ADVISOR); 18 return true; 19 } 20 } 21 return false; 22 }
-> AspectJProxyUtils# isAspectJAdvice
1 // 判断Advisor中是否包含Advice 2 private static boolean isAspectJAdvice(Advisor advisor) { 3 // advisor是InstantiationModelAwarePointcutAdvisor类型 4 // advisor中持有的Advice是AbstractAspectJAdvice类型 5 // advisosr是PointcutAdvisor类型,并且 持有的pointcut是AspectJExpressionPointcut类型 6 return (advisor instanceof InstantiationModelAwarePointcutAdvisor || 7 advisor.getAdvice() instanceof AbstractAspectJAdvice || 8 (advisor instanceof PointcutAdvisor && 9 ((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut)); 10 }
-> AbstractBeanFactoryPointcutAdvisor# getAdvice 获取advice对象
1 public Advice getAdvice() { 2 // 获取当前Advisor的advice对象 3 Advice advice = this.advice; 4 // advice不为空,直接返回 5 if (advice != null) { 6 return advice; 7 } 8 9 // 判断当前Advice是否为一个单例的 10 if (this.beanFactory.isSingleton(this.adviceBeanName)) { 11 12 // 创建advice对象 13 advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class); 14 // 将创建的Advice对象设置进Advisor的advice属性 15 this.advice = advice; 16 // 返回transactionInterceptor对象 17 return advice; 18 } 19 }

Advisor中的advice属性创建的入口找到了,接下来看看Advice是如何创建的。
2、创建Advice核心伪代码
TransactionInterceptor中包含两个属性,NameMatchTransactionAttributeSource、transcationManager,transcationManager的bean,在缓存中获取;NameMatchTransactionAttributeSource需要在填充属性时创建bean信息。
1、Advice实例化
2、属性填充

1 // 解析propertyValues中value为BeanDefinition的属性 2 public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { 3 // value为BeanDefinition类型 4 if (value instanceof BeanDefinition) { 5 6 7 // 将value强转为BeanDefinition对象 8 BeanDefinition bd = (BeanDefinition) value; 9 // 拼装内部Bean名:"(inner bean)#"+bd的身份哈希码的十六进制字符串形式 10 String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + 11 ObjectUtils.getIdentityHexString(bd); 12 //根据innerBeanName和bd解析出内部Bean对象,创建bean 13 return resolveInnerBean(argName, innerBeanName, bd); 14 } 15 }
-> BeanDefinitionValueResolver# resolveInnerBean 创建bean对象
1 private Object resolveInnerBean(Object argName, String innerBeanName, BeanDefinition innerBd) { 2 //定义一个用于保存innerBd与beanDefinition合并后的BeanDefinition对象的变量 3 RootBeanDefinition mbd = null; 4 try { 5 //获取innerBd与beanDefinition合并后的BeanDefinition对象 6 mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition); 7 8 // 获取唯一的beanName 9 String actualInnerBeanName = innerBeanName; 10 // 如果mbd要求时必须是单例的 11 if (mbd.isSingleton()) { 12 //调整innerBeanName,直到该beanName在工厂中唯一。最后将结果赋值给actualInnerBeanName 13 actualInnerBeanName = adaptInnerBeanName(innerBeanName); 14 } 15 16 // 创建actualInnerBeanName的Bean对象 17 Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null); 18 19 //返回actualInnerBeanName的Bean对象 20 return innerBean; 21 }
NameMatchTransactionAttributeSource创建完成后,设置进Advice中。至此,事务相关对象的都已创建完成。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)