首页 > 编程语言 >Spring 事务源码(三):事务相关对象的创建

Spring 事务源码(三):事务相关对象的创建

时间:2023-01-02 20:55:15浏览次数:59  
标签:事务 对象 Spring Advice Advisor bean 源码 创建 advice

  事务源码(二)中,已经分析了beanDefinition的加载,下面来创建对应beanDefinition的bean。

1、PropertySourcesPlaceholderConfigurer 创建占位符处理的bean

  PropertySourcesPlaceholderConfigurer实现了BeanFactoryPostProcessor、PriorityOrdered接口,在IOC容器刷新过程中,invokeBeanFactoryPostProcessors处理实现了BeanFactoryPostProcessor接口的bean,实例化核心伪代码   PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
 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

  Advisor与其他bean之间的依赖关系:  

  在AOP源码(三):创建AOP相关的Bean中提到Advisor的创建是在创建首个普通bean标签的对象实例化之前处理的,本次案例中就是在创建dataSource实例化之前处理的,即AbstractAutowireCapableBeanFactory#createBean-》AbstractAutowireCapableBeanFactoryresolveBeforeInstantiation处理的。

  AspectJExpressionPointcutAdvisor的创建时机已明确,那么Advisor中的属性对象是在何时触发创建的呢?

  在事务源码(二):beanDefinition的准备-配置文件加载中提到pointcut-ref、advice-ref被设置在Advisor的beanDefinition的propertyValues属性中,而propertyValues中内容是在bean实例化完成之后,完成bean属性填充时需要用到,按照这个思路看看Advisor在属性填充做了什么事情?

  AbstractAutowireCapableBeanFactory#populateBean bean属性填充,核心伪代码
 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属性填充核心伪代码

  AbstractAutowireCapableBeanFactory#applyPropertyValues 使用propertyValues属性完成bean的填充核心伪代码
 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是在哪里创建的呢?

  我们接着往下分析,在Spring中若对哪个方法开启了事务,则这个方法所在的类必须要被代理,利用AOP的环绕通知、异常通知来处理事务的开启、提交和回滚操作。在AOP源码(四):创建被代理类的代理对象中提到,在创建被代理类的代理对象createProxy时,会添加一个ExoseInvocationInterceptor的Advice,组装AOP执行链,ExoseInvocationInterceptor的Advice用作AOP执行流程 - 责任链控制器。在创建ProductDao或ProductService的bean对象,创建代理对象时会不会创建TransactionInterceptor的Advice对象,并将该Advice对象设置进Advisor中呢?

4、TransactionInterceptor 创建事务通知Advice

  被代理类的代理对象,是在初始化被代理类的后置处理器applyBeanPostProcessorsAfterInitialization中创建的。

4.1、Advice创建核心流程图

4.2、Advice创建

1、创建Advice的时机

AbstractAutoProxyCreator# wrapIfNecessary -> AbstractAdvisorAutoProxyCreator# getAdvicesAndAdvisorsForBean -> AbstractAdvisorAutoProxyCreator# findEligibleAdvisors -> AbstractAdvisorAutoProxyCreator# extendAdvisors 拓展Advisor核心伪代码
1 // 拓展通知-> 添加 ExposeInvocationInterceptor、TransactionIntercecptor
2 protected void extendAdvisors(List<Advisor> candidateAdvisors) {
3    AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
4 }
-> AspectJProxyUtils# makeAdvisorChainAspectJCapableIfNecessary 获取事务执行链核心伪代码
 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 }
  在创建bean标签的首个被代理类的代理对象时,获取拦截器执行链时,会判断当前Advisor中的Advice是否为空,若不为空,直接返回Advisor中的Advice对象;若为空,创建Advice对象,并将对象设置进Advisor的advice属性中,完成创建过程。

  Advisor中的advice属性创建的入口找到了,接下来看看Advice是如何创建的。

2、创建Advice核心伪代码

  TransactionInterceptor中包含两个属性,NameMatchTransactionAttributeSource、transcationManager,transcationManager的bean,在缓存中获取;NameMatchTransactionAttributeSource需要在填充属性时创建bean信息。

1、Advice实例化

2、属性填充

  Advice实例化完成,其中有关method的事务信息NameMatchTransactionAttributeSource在beanDefinition的propertyValues中。在属性填充时,完成属性的赋值。   0   创建NameMatchTransactionAttributeSource对象,核心伪代码 AbstractAutowireCapableBeanFactory# populateBean   -> AbstractAutowireCapableBeanFactory# applyPropertyValues   -> BeanDefinitionValueResolver# resolveValueIfNecessary 属性填充创建transactionAttributeSource对象
 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中。至此,事务相关对象的都已创建完成。

标签:事务,对象,Spring,Advice,Advisor,bean,源码,创建,advice
From: https://www.cnblogs.com/RunningSnails/p/17020456.html

相关文章