zoukankan      html  css  js  c++  java
  • Spring源码解析之事务(一)

    1、开启事务注解:@EnableTransactionManagement

    2、向容器注入DataSourceTransactionManager对象,并向其传入DataSource对象。

    @Configuration
    @ComponentScan
    @EnableTransactionManagement
    @EnableAspectJAutoProxy
    public class TxConfig {
        @Bean
        public DataSource dataSource() throws PropertyVetoException {
            ComboPooledDataSource dataSource = new ComboPooledDataSource(true);
            dataSource.setUser("root");
            dataSource.setPassword("123456");
            dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false");
            dataSource.setInitialPoolSize(3);
            dataSource.setMaxPoolSize(10);
            dataSource.setMinPoolSize(3);
            dataSource.setAcquireIncrement(3);
            return dataSource;
        }
        @Bean
        @Autowired
        public JdbcTemplate jdbcTemplate(DataSource ds) throws PropertyVetoException {
            JdbcTemplate jdbcTemplate = new JdbcTemplate(ds);
            return jdbcTemplate;
        }
        @Bean
        public PlatformTransactionManager transactionManager() throws PropertyVetoException {
            return new DataSourceTransactionManager(dataSource());
        }
    }
    @Repository
    public class UserDao {
        @Autowired
        public JdbcTemplate jdbcTemplate;
        @Transactional
        public void insert() {
            String sql = "INSERT INTO `user` VALUES (7, 'name', '123123', 'test', '44422', '1231231')";
            jdbcTemplate.execute(sql);
            int i=10/0;
        }
    }
    @Service
    public class UserService {
        @Autowired
        public UserDao userDao;
        
        public void insertUser(){
            userDao.insert();
            System.out.println("UserService执行成功insertUser()方法");
        }
    }
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class Test {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(TxConfig.class);
            System.out.println("容器初始化成功");
            UserService userService = annotationConfigApplicationContext.getBean(UserService.class);
            userService.insertUser();
        }
    }
    

      

    3、源码解析:

    @EnableTransactionManagement注解导入TransactionManagementConfigurationSelector类。TransactionManagementConfigurationSelector类继承了ImportSelector接口,该接口的selectImports方法会返回需要被导入到容器中的类名,TransactionManagementConfigurationSelector的selectImports方法向容器中导入两个组件,分别是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。

      AutoProxyRegistrar类为容器注册InfrastructureAdvisorAutoProxyCreator类(如果@EnableTransactionManagement注解的属性AdviceMode为                ---AdviceMode.PROXY)。而aop时注入的是AnnotationAwareAspectJAutoProxyCreator类。

        InfrastructureAdvisorAutoProxyCreator类也是一个后置处理器。利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用。

      ProxyTransactionManagementConfiguration类是配置类,为容器注册事务增强器BeanFactoryTransactionAttributeSourceAdvisor(bean的名字org.springframework.transaction.config.internalTransactionAdvisor),需要为其添加事务属性(AnnotationTransactionAttributeSource)

        AnnotationTransactionAttributeSource实现了接口TransactionAttributeSource,为其注入注解解析器:SpringTransactionAnnotationParser。其中SpringTransactionAnnotationParser是TransactionAnnotationParser的实现类,TransactionAnnotationParser:基于已知的注释类型解析给定方法或类的事务属性。这实际上将已知的事务注释解析为Spring的元数据属性类。如果方法/类不是事务性的,则返回null。

    @Configuration
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
    	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
    		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
    		advisor.setTransactionAttributeSource(transactionAttributeSource());
    		advisor.setAdvice(transactionInterceptor());//添加拦截器
    		advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
    		return advisor;
    	}
    
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public TransactionAttributeSource transactionAttributeSource() {
    		return new AnnotationTransactionAttributeSource();
    	}
    
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public TransactionInterceptor transactionInterceptor() {
    		TransactionInterceptor interceptor = new TransactionInterceptor();
    		interceptor.setTransactionAttributeSource(transactionAttributeSource());
    		if (this.txManager != null) {
    			interceptor.setTransactionManager(this.txManager);
    		}
    		return interceptor;
    	}
    
    }
    

      ProxyTransactionManagementConfiguration配置类也为容器注入事务拦截器,TransactionInterceptor保存了事务属性信息和事务管理器。

         @Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public TransactionInterceptor transactionInterceptor() {
    		TransactionInterceptor interceptor = new TransactionInterceptor();
    		interceptor.setTransactionAttributeSource(transactionAttributeSource());
    		if (this.txManager != null) {
    			interceptor.setTransactionManager(this.txManager);
    		}
    		return interceptor;
    	}
    

     

    4、动态代理源码解析:当UserDao.java的insert方法带有注解:@Transactional,且LogAspects切面类具有execution( public void com.transaction.UserDao.insert(..))的pointcut(切入点)。解析UserDao类实例化返回代理对象的源码(Spring事务与Spring AOP对比学习):

    UserDao实例化后,创建代理对象源码起始点(AbstractAdvisorAutoProxyCreator类的wrapIfNecessary(Object bean, String beanName, Object cacheKey)方法,该方法返回所有符合当前类的通知):

      ------>  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

         ------>List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);

    	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    		List<Advisor> candidateAdvisors = findCandidateAdvisors();
    		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    		extendAdvisors(eligibleAdvisors);
    		if (!eligibleAdvisors.isEmpty()) {
    			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    		}
    		return eligibleAdvisors;
    	}
    

      1)查询全部的advisor(通知),然后再筛选符合当前类的通知(advisor)。方法findCandidateAdvisors() ----> this.advisorRetrievalHelper.findAdvisorBeans()

    ---->advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false); 方法获取到org.springframework.transaction.config.internalTransactionAdvisor,即事务为容器注册的事务增强器BeanFactoryTransactionAttributeSourceAdvisor。

      this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法为容器注入aop相关的通知,包括前置通知,后置通知等等。

            @Override
    	protected List<Advisor> findCandidateAdvisors() {
    		// Add all the Spring advisors found according to superclass rules.
    		List<Advisor> advisors = super.findCandidateAdvisors();
    		// Build Advisors for all AspectJ aspects in the bean factory.
    		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    		return advisors;
    	}
    

      2)List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);获取符合当前类的通知

         ------>canApply(candidate, clazz, hasIntroductions),循环遍历通知,判断当前candidate通知是否作用当前类。事务增强器实现了PointcutAdvisor接口

            ------>canApply(pca.getPointcut(), targetClass, hasIntroductions),获取事务增强器的切入点pointcut:该切入点继承了对象:           TransactionAttributeSourcePointcut,该类重写了getTransactionAttributeSource方法,返回AnnotationTransactionAttributeSource对象。

                ------>methodMatcher.matches(method, targetClass)) ,获取UserDao以及接口和父类的全部方法,然后判断该通知是否匹配该方法

                  ------>TransactionAttributeSource tas = getTransactionAttributeSource();获取为事务增强器注入的事务属性类。

                      ------>TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);

                       ------>TransactionAttribute txAttr = findTransactionAttribute(specificMethod)            

                         ------->determineTransactionAttribute(method);

                             ------->源码如下(先获取注解解析器SpringTransactionAnnotationParser然后用其去判断是否匹配)

                              -------->AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae,  Transactional.class);

    	protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
    		if (ae.getAnnotations().length > 0) {
    			for (TransactionAnnotationParser annotationParser : this.annotationParsers) {//获取注入的注解解析器
    				TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
    				if (attr != null) {
    					return attr;
    				}
    			}
    		}
    		return null;
    	}
    

     

    5、执行事务方法:

      userDao.insert();

        -----> public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)  ,动态代理对象拦截

          ----->List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);  adviced是AdvisedSupport对象,管理器。

            ----->cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);   

              ----->循环遍历adviced下(AdvisedSupport对象)的全部通知(Advisor)

                 ----->MethodInterceptor[] interceptors = registry.getInterceptors(advisor);,获取该通知的拦截器列表

                   ----->Advice advice = advisor.getAdvice(); 获取advice,事务事务增强器的拦截器即TransactionInterceptor保存了事务属性信息和事务管理器。将该拦截器添加到该拦截器链中。

                ----->执行拦截器链:retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

             ----->依次调用拦截器链中的拦截器的invoke(this)方法,该方法执行完后会调用传参变量(MethodInvocation)的proceed()进而调用下一个拦截器的invoke(this)方法,这也是aop的原理。

                ----->TransactionInterceptor的invoke方法:

    	@Override
    	public Object invoke(final MethodInvocation invocation) throws Throwable {
    		// Work out the target class: may be {@code null}.
    		// The TransactionAttributeSource should be passed the target class
    		// as well as the method, which may be from an interface.
    		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    
    		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
    		return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
    			@Override
    			public Object proceedWithInvocation() throws Throwable {
    				return invocation.proceed();
    			}
    		});
    	}
    

      invokeWithinTransaction方法(spring事务的核心源码):

    public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
       //protected修饰,不允许其他包和无关类调用
        protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
            // 获取对应事务属性.如果事务属性为空(则目标方法不存在事务)
            final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
         // 根据事务的属性获取beanFactory中的PlatformTransactionManager(spring事务管理器的顶级接口),一般这里或者的是DataSourceTransactiuonManager
            final PlatformTransactionManager tm = determineTransactionManager(txAttr);
         // 目标方法唯一标识(类.方法,如service.UserServiceImpl.save)
            final String joinpointIdentification = methodIdentification(method, targetClass);
         //如果txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,执行目标增强     ①
            if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
                //看是否有必要创建一个事务,根据事务传播行为,做出相应的判断
                TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
                Object retVal = null;
                try {
              //回调方法执行,执行目标方法(原有的业务逻辑)
                    retVal = invocation.proceedWithInvocation();
                }
                catch (Throwable ex) {
                    // 异常回滚
                    completeTransactionAfterThrowing(txInfo, ex);
                    throw ex;
                }
                finally {
              //清除信息
                    cleanupTransactionInfo(txInfo);
                }
            //提交事务
                commitTransactionAfterReturning(txInfo);
                return retVal;
            }
         //编程式事务处理(CallbackPreferringPlatformTransactionManager) 不做重点分析
            else {
                try {
                    Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
                            new TransactionCallback<Object>() {
                                @Override
                                public Object doInTransaction(TransactionStatus status) {
                                    TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                                    try {
                                        return invocation.proceedWithInvocation();
                                    }
                                    catch (Throwable ex) {
                                        if (txAttr.rollbackOn(ex)) {
                                            // A RuntimeException: will lead to a rollback.
                                            if (ex instanceof RuntimeException) {
                                                throw (RuntimeException) ex;
                                            }
                                            else {
                                                throw new ThrowableHolderException(ex);
                                            }
                                        }
                                        else {
                                            // A normal return value: will lead to a commit.
                                            return new ThrowableHolder(ex);
                                        }
                                    }
                                    finally {
                                        cleanupTransactionInfo(txInfo);
                                    }
                                }
                            });
    
                    // Check result: It might indicate a Throwable to rethrow.
                    if (result instanceof ThrowableHolder) {
                        throw ((ThrowableHolder) result).getThrowable();
                    }
                    else {
                        return result;
                    }
                }
                catch (ThrowableHolderException ex) {
                    throw ex.getCause();
                }
            }
        }
    }
    

      

      

      

     

  • 相关阅读:
    ACM模板——次短路及K短路
    ACM模板——最小生成树
    Leetcode-743 Network Delay Time(网络延迟时间)
    ACM模板——最短路
    HDU-2037 今年暑假不AC
    Leetcode-1015 Numbers With Repeated Digits(至少有 1 位重复的数字)
    Leetcode-1014 Capacity To Ship Packages Within D Days(在 D 天内送达包裹的能力)
    Leetcode-1013 Pairs of Songs With Total Durations Divisible by 60(总持续时间可被 60 整除的歌曲)
    Leetcode-1012 Complement of Base 10 Integer(十进制整数的补码)
    LeetCode--204--计数质数
  • 原文地址:https://www.cnblogs.com/yaohuiqin/p/10487709.html
Copyright © 2011-2022 走看看