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