• spring 事务通俗易懂总结-初始化篇


    过年前项目不是那么忙了,利用这段时间看看spring的事务处理的源码,现在总结如下

    1 本篇为初始化篇,通俗的说就是所谓的事务管理,在spring启动的时候,该对某些方法做事务增强就已经确定好了。本篇就是要分析这部分源码

    2 下一篇为分析执行部分,尤其是针对require require_new这种需要挂起当前事务的传播特性spring源码是怎么写的

    进入主题:

      1 要使用声明式事务就要在spring的配置文件里写注解

               <tx:annotation-driven> 注意到 命令空间 tx 所以我们找到了对此命令空间的解析类 TxNamespaceHandler

      2 在 TxNamespaceHandler中会发现. 

       registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());继续分析AnnotationDrivenBeanDefinitionParser。

       

    @Override
    	public BeanDefinition parse(Element element, ParserContext parserContext) {
    		registerTransactionalEventListenerFactory(parserContext);
    		String mode = element.getAttribute("mode");
    		if ("aspectj".equals(mode)) {
    			// mode="aspectj"
    			registerTransactionAspect(element, parserContext);
    		}
    		else {
    			// mode="proxy"
    			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    		}
    		return null;
    	}
    

      继续看 AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext); 干了什么

    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
    			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
    
    			String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
    			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
    				Object eleSource = parserContext.extractSource(element);
    
    				// Create the TransactionAttributeSource definition.
    				RootBeanDefinition sourceDef = new RootBeanDefinition(
    						"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
    				sourceDef.setSource(eleSource);
    				sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    				String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
    
    				// Create the TransactionInterceptor definition.
    				RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
    				interceptorDef.setSource(eleSource);
    				interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    				registerTransactionManager(element, interceptorDef);
    				interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
    				String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
    
    				// Create the TransactionAttributeSourceAdvisor definition.
    				RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
    				advisorDef.setSource(eleSource);
    				advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    				advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
    				advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
    				if (element.hasAttribute("order")) {
    					advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
    				}
    				parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
    
    				CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
    				compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
    				compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
    				compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
    				parserContext.registerComponent(compositeDef);
    

     

      AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);     
    该方法的作用就是初始化一个类 该类为InfrastructureAdvisorAutoProxyCreator。
    该类最重要的属性就是实现了BeanPostProcessor。
    简单说说BeanPostProcessor的作用。BeanPostProcessor接口有个方法postProcessAfterInitialization,实现该方法就会对一个java bean初始化的时候做一个增强。
    没错,我们在使用spring做事务控制的时候,都会写一个Service接口 并写ServiceImpl实现类,其实这个实现类就已经不是我们当初写的了,而是经过了BeanPostProcessor的增强。
    除了这个InfrastructureAdvisorAutoProxyCreator初始化还有三个Bean,分别是

      AnnotationTransactionAttributeSource,TransactionInterceptor,

      BeanFactoryTransactionAttributeSourceAdvisor。这三个Bean关系是这样的。

      AnnotationTransactionAttributeSource和 TransactionInterceptor作为属性注入到 BeanFactoryTransactionAttributeSourceAdvisor。

      简单的说下这三个bean的作用,可以有一个感性认识:

      BeanFactoryTransactionAttributeSourceAdvisor -- 是一个advisor也就是增强器,这样在PostBeanProcessor处理的时候 该advisor会被选出来

      AnnotationTransactionAttributeSource -- 包装了方法的事务属性,比如某个方法的隔离级别 传播特性 回滚配置

      TransactionInterceptor -- 干具体事的,这里面的方法就是对目标方法增强的具体实现。开启事务,回滚或者提交下面详细看一下PostBeanProcessor是怎么执行的

      顺着PostBeanProcessor对ServiceImp做增强的思路,接下来就是看看这个增强是怎么做的

    AbstractAutoProxyCreator.postProcessAfterInitialization
    @Override
    	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    		if (bean != null) {
    			Object cacheKey = getCacheKey(bean.getClass(), beanName);
    			if (!this.earlyProxyReferences.contains(cacheKey)) {
    				return wrapIfNecessary(bean, beanName, cacheKey);
    			}
    		}
    		return bean;
    	}
    
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
    			return bean;
    		}
    		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    			return bean;
    		}
    		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    			this.advisedBeans.put(cacheKey, Boolean.FALSE);
    			return bean;
    		}
    
    		// Create proxy if we have advice.
    		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    		if (specificInterceptors != DO_NOT_PROXY) {
    			this.advisedBeans.put(cacheKey, Boolean.TRUE);
    			Object proxy = createProxy(
    					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    			this.proxyTypes.put(cacheKey, proxy.getClass());
    			return proxy;
    		}
    
    		this.advisedBeans.put(cacheKey, Boolean.FALSE);
    		return bean;
    	}
    

      这部分的实现很清晰:1 找增强器 2 根据增强器对目标bean增强

      其中 找增强器的过程就是把该bean通过class反射机制遍历其中的method,只要有一个method上有注解@Transactional 。该bean就满足被增强的条件,会放入缓存,保存这个方法相关的隔离级别和传播特性等事务属性。当找到了合适的增强器后,使用动态代理对目标类的目标方法做增强。

      这样事务的初始化就完成了



      

       

  • 相关阅读:
    Docker安装
    MVC-HtmlHelper简单总结
    D3.js
    分布式事务seata
    彻底搞懂JAVA路径问题
    idea 代码生成
    自动生成 serialVersionUID 的设置
    狂神说SSM框架系列连载
    缓存穿透、缓存击穿、缓存雪崩区别和解决方案
    多线程
  • 原文地址:https://www.cnblogs.com/juniorMa/p/10278455.html
Copyright © 2020-2023  润新知