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();
            }
        }
    }
}

  

  

  

 

posted @ 2019-03-08 10:25  yaohuiqin  阅读(684)  评论(0编辑  收藏  举报