程序地带

Spring源码深度解析之事务


Spring源码深度解析之事务


目录


一、JDBC方式下的事务使用示例


  (1)创建数据表结构


  (2)创建对应数据表的PO


  (3)创建表和实体之间的映射


  (4)创建数据操作接口


  (5)创建数据操作接口实现类


  (6)创建Spring配置文件


  (7)测试


二、事务自定义标签


(一)注册InfrastructureAdvisorAutoProxyCreator


(二)获取对应class/method的增强器


  (1)寻找候选增强器


  (2)候选增强器中寻找到匹配项


三、事务增强器


(一)创建事务


  (1)获取事务


  (2)处理已经存在的事务


  (3)准备事务信息


(二)回滚处理


  (1)回滚条件


  (2)回滚处理


  (3)回滚后的信息清除


(三)事务提交


 


      Spring声明式事务让我们从复杂的事务处理中得到解脱,使我们再也不需要去处理获得连接、关闭连接、事务提交和回滚等操作。再也不需要在与事务相关的方法中处理大量的try…catch…finally代码。Spring中事务的使用虽然已经相对简单得多,但是,还是有很多的使用及配置规划,有兴趣的读者可以自己查阅相关资料进行深入的研究,这里只列举出最常用的使用方法。


      同样,我们还是以最简单的示例来进行直观的介绍。


一、JDBC方式下事务使用示例


(1)创建数据表结构


1 CREATE TABLE "user"(
2 "id" int(11) NOT NULL auto_increment,
3 "name" varchar(255) default null,
4 "age" int(11) default null,
5 "sex" varchar(255) default null,
6 PRIMARY KEY ("id")
7 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

(2)创建对应数据表的PO


1 public class User {
2 private int id;
3 private String name;
4 private int age;
5 private String sex;
6 //省略set/get方法
7 }

(3)创建表和实体之间的映射


1 public class UserRowMapper implements RowMapper {
2 @Override
3 public Object mapRow(ResultSet set, int index) throws SQLException {
4 User person = new User(set.getInt("id"), set.getString("name"), set.getInt("age"), set.getString("sex"));
5 return person;
6 }
7 }

(4)创建数据操作接口


1 @Transactional(propagation-Propagation.REQUIRED)
2 public interface UserService {
3 public void save(User user) throws Exception;
4 }

(5)创建数据操作接口实现类


1 public class UserServiceImpl implements UserService {
2 private JdbcTemplate jdbcTemplate;
3
4 //设置数据源
5 public void setDataSource(DataSource dataSource) {
6 this.jdbcTemplate = new JdbcTemplate(dataSource);
7 }
8
9 public void save(User user) throws Exception {
10 jdbcTemplate.update("insert into user(name, age, sex) value(?, ?, ?)",
11 new Object[] {user.getName(), usr.getAge(), user.getSex()},
12 new int[] {java.sql.Types.VARCHAR, java.sql.Type.INTEGER, java.sql.Types.VARCHAR});
13
14 //事务测试,加上这句代码则数据不会保存到数据库中
15 throw new RuntimeException("aa");
16 }
17
18 }

(6)创建Spring配置文件


1 <?xml version="1.0" encoding="UTF-8" ?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://w3.org/2001/XMLSchema-instance"
4 xmlns:tx="http://www.springframework.org/schema/tx"
5 xmlns:context="http://www.springframework.org/schema/context"
6 xsi:schemaLocation="http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
8 http://www.springframework.org/schema/context
9 http://www.springframework.org/schema/context/spring-context-2.5.xsd
10 http://www.springframework.org/schema/tx
11 http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
12
13 <tx:annotation-driven transaction-manager="transactionManager"/>
14
15 <bean id="transactionManager" class="org.springframe.jdbc.datasource.DataSourceTransactionManager">
16 <property name="dataSource" ref="dataSource"/>
17 </bean>
18
19 //配置数据源
20 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
21 <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
22 <property name="uri" value="jdbc:mysql://localhost:3306/lexueba"/>
23 <property name="username" value="root"/>
24 <property name="password" value="haojia0421xixi"/>
25 <!--连接池启动时的初始值-->
26 <property name="initialSize" value="1"/>
27 <!--连接池的最大值-->
28 <property name="maxActive" value="300"/>
29 <!--最大空闲值,当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止-->
30 <property name="maxIdle" value="2"/>
31 <!--最小空闲值,当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请-->
32 <property name="minIdle" value="1"/>
33 </bean>
34
35 <!--配置业务 bean:PersonServiceBean -->
36 <bean id="userService" class="service.UserServiceImple">
37 <!--向属性dataSource注入数据源-->
38 <property name="dataSource" ref="dataSource"></property>
39 </bean>
40
41 </beans>

(7)测试


1 public static void main(String[] args) throws Exception {
2 ApplicationContext act = new ClassPathXmlApplicationContext("bean.xml");
3
4 UserService userService = (UserService) act.getBean("userService");
5 User user = new User();
6 user.setName("张三CCC");
7 user.setAge(20);
8 user.setSex("男");
9 //保存一条记录
10 userService.save(user);
11 }

      上面测测试示例中,UserServiceImpl类对接口UserService中的save函数的实现最后加入了一句抛出异常的代码:throw new RuntimeException(“aa”)。当注释掉这段代码执行测试类,那么会看到数据被成功的保存到了数据库中,但是如果加入这段代码再次运行测试类,发现此处的操作并不会将数据保存到数据库中。


      注意:默认情况下,Spring中的事务处理只对RuntimeException方法进行回滚,所以,如果此处将RuntimeException替换成普通的Exception不会产生回滚效果。


 


二、事务自定义标签


  对于Spring中事务功能的代码分析。我们首先从配置文件开始入手,在配置文件中有这样一个配置<tx:annotation-driven/>。可以说此处配置是事务的开关,如果没有此处的配置,那么Spring中将不存在事务的功能。那么我们就从这个配置开始分析。


  根据之前的分析。我们因此可以判断,在自定义标签中的解析过程中一定是做了一些辅助性的操作,于是我们先从自定义的标签入手进行分析。


  对于关键字annotation-driven,在TxNamespaceHandler类(package org.springframework.transaction.config)中的init()方法中进行了处理:


1 public void init() {
2 registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
3 registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
4 registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
5 }

  根据自定义标签的使用规则及上面的代码,可以知道,在遇到诸如<tx:annotation-driven为开头的配置后,Spring都会使用AnnotationDrivenBeanDefinitionParser类(package org.springframework.transaction.config)的parse()方法进行解析。


1 public BeanDefinition parse(Element element, ParserContext parserContext) {
2 registerTransactionalEventListenerFactory(parserContext);
3 String mode = element.getAttribute("mode");
4 if ("aspectj".equals(mode)) {
5 // mode="aspectj"
6 registerTransactionAspect(element, parserContext);
7 if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
8 registerJtaTransactionAspect(element, parserContext);
9 }
10 }
11 else {
12 // mode="proxy"
13 AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
14 }
15 return null;
16 }

  在解析中存在对于mode属性的判断,根据代码,如果我们需要使用AspectJ的方式进行事务切入(Spring中的事务是以AOP为基础的),那么可以使用这样的配置:


<tx:annotation-driven transaction-manager="transactionManager"/ mode="aspectJ">
(一)注册InfrastructureAdvisorAutoProxyCreator

      我们以默认配置为例子进行分析,进入AopAutoProxyConfigurer类(AnnotationDrivenBeanDefinitionParser类的内部类)的configureAutoProxyCreator函数:


1 public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
2 AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
3
4 String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
5 if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
6 Object eleSource = parserContext.extractSource(element);
7
8 // Create the TransactionAttributeSource definition.
9 //创建TransactionAttributeSource的bean
10 RootBeanDefinition sourceDef = new RootBeanDefinition(
11 "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
12 sourceDef.setSource(eleSource);
13 sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
14 //注册bean,并使用Spring中的定义规则生成beanname
15 String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
16
17 // Create the TransactionInterceptor definition.
18 //创建TransactionInterceptor的bean
19 RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
20 interceptorDef.setSource(eleSource);
21 interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
22 registerTransactionManager(element, interceptorDef);
23 interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
24 String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
25
26 // Create the TransactionAttributeSourceAdvisor definition.
27 //创建TransactionAttributeSourceAdvisor的bean
28 RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
29 advisorDef.setSource(eleSource);
30 advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
31 //将sourceName的bean注入advisorDef的transactionAttributeSource属性中
32 advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
33 //将interceptorName的bean注入advisorDef的adviceBeanName属性中
34 advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
35 //如果配置了order属性,则加入到bean中
36 if (element.hasAttribute("order")) {
37 advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
38 }
39 parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);
40
41 //创建CompositeComponentDefinition
42 CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
43 compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
44 compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
45 compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
46 parserContext.registerComponent(compositeDef);
47 }
48 }

  上面的代码注册了代理类及三个bean,很多读者会直接略过,认为只是注册三个bean而已,确实,这里只注册量三个bean,但是这三个bean支撑了整个事务的功能,那么这三个bean是怎么组织起来的呢?


      首先,其中的两个bean被注册到了一个名为advisorDef的bean中,advisorDef使用BeanFactoryTransactionAttributeSourceAdvisor作为其class属性。也就是说BeanFactoryTransactionAttributeSourceAdvisor代表着当前bean,具体代码如下:


advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);

      那么如此组装的目的是什么呢?先留下一个悬念,接着分析代码。上面configureAutoProxyCreator函数中的第一句貌似很简单但却是很重要的代码:


AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

      进入这个函数,AopNamespaceUtils类(package org.springframework.aop.config)的registerAutoProxyCreatorIfNecessary函数:


1 public static void registerAutoProxyCreatorIfNecessary(
2 ParserContext parserContext, Element sourceElement) {
3
4 BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
5 parserContext.getRegistry(), parserContext.extractSource(sourceElement));
6 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
7 registerComponentIfNecessary(beanDefinition, parserContext);
8 }

  上面函数又调用了AopConfigUtils类(package org.springframework.aop.config)的registerAutoProxyCreatorIfNecessary函数:


1 public static BeanDefinition registerAutoProxyCreatorIfNecessary(
2 BeanDefinitionRegistry registry, @Nullable Object source) {
3
4 return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
5 }

      对于解析来的额代码流程AOP中已经有所分析,上面两个函数主要的目的是注册InfrastructureAdvisorAutoProxyCreator类型(package org.springframework.aop.framework.autoproxy)的bean,那么注册这个类的目的是什么呢?


  查看该类的层次结构,可以看到InfrastructureAdvisorAutoProxyCreator继承自AbstractAdvisorAutoProxyCreator继承自AbstractAutoProxyCreator继承自SmartInstantiationAwareBeanPostProcessor继承自InstantiationAwareBeanPostProcessor(含postProcessAfterInitialization方法),也就是说在Spring中,所有bean实例化时Spring都会保证调用其postProcessAfterInitialization方法。其实现是在父类AbstractAutoProxyCreator类中实现。


      以之前的示例为例,当实例化userService的bean时便会调用此方法,AbstractAutoProxyCreator类(packageorg.springframework.aop.framework.autoproxy)的postProcessAfterInitialization方法:


1 public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
2 if (bean != null) {
3 //根据给定的bean的class和name构建出key,格式:beanClassName_beanName
4 Object cacheKey = getCacheKey(bean.getClass(), beanName);
5 if (this.earlyProxyReferences.remove(cacheKey) != bean) {
6 //一个非常核心的方法:wrapIfNecessary(),如果它适合被代理,则需要封装指定的bean。
7 return wrapIfNecessary(bean, beanName, cacheKey);
8 }
9 }
10 return bean;
11 }

  这里实现的主要目的是对指定的bean进行封装,当然首先要确定是否需要封装,检测以及封装的的工作都委托给了wrapIfNecessary函数进行,AbstractAutoProxyCreator类的wrapIfNecessary方法:


1 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
2 //如果已经处理过
3 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
4 return bean;
5 }
6 //这个bean无需增强
7 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
8 return bean;
9 }
10 //判断给定的bean是否是一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要代理。
11 //所谓InfrastructureClass就是指Advice/PointCut/Advisor等接口的实现类。
12 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
13 this.advisedBeans.put(cacheKey, Boolean.FALSE);
14 return bean;
15 }
16
17 // 如果存在增强方法则创建代理
18 //获取这个bean的advice
19 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
20 //如果获取到了增强则需要针对增强创建代理
21 if (specificInterceptors != DO_NOT_PROXY) {
22 this.advisedBeans.put(cacheKey, Boolean.TRUE);
23 //创建代理
24 Object proxy = createProxy(
25 bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
26 this.proxyTypes.put(cacheKey, proxy.getClass());
27 return proxy;
28 }
29
30 this.advisedBeans.put(cacheKey, Boolean.FALSE);
31 return bean;
32 }

      WrapIfNecessary函数功能实现起来很复杂,但是逻辑上理解起来还是相对简单的,在wrapIfNecessary函数中主要的工作如下:


      ①找出指定bean对应的增强器。


      ②根据找出的增强器创建代理。


      听起来似乎简单的逻辑,Spring中又做了哪些复杂的工作呢?对于创建代理的部分,通过之前的分析大家已经很熟悉了,但是对于增强器的获取,Spring又是怎么做的呢?


(二)获取对应的class/method的增强器


      获取指定bean对应的增强器,其中包含两个关键字:增强器和对应。也就是说在getAdvicesAndAdvisorsForBean函数中,不但要找出增强器,而且还需要判断增强器是否满足要求。AbstractAutoProxyCreator类的wrapIfNecessary方法中调用了getAdvicesAndAdvisorsForBean,AbstractAutoProxyCreator类只对该方法进行定义,真正实现在其子类AbstractAdvisorAutoProxyCreator(package org.springframework.aop.framework.autoproxy)中:


1 protected Object[] getAdvicesAndAdvisorsForBean(
2 Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
3
4 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
5 if (advisors.isEmpty()) {
6 return DO_NOT_PROXY;
7 }
8 return advisors.toArray();
9 }

   上述函数调用了该类中的findEligibleAdvisors函数:


1 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
2 List<Advisor> candidateAdvisors = findCandidateAdvisors();
3 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
4 extendAdvisors(eligibleAdvisors);
5 if (!eligibleAdvisors.isEmpty()) {
6 eligibleAdvisors = sortAdvisors(eligibleAdvisors);
7 }
8 return eligibleAdvisors;
9 }

      其实我们也渐渐地体会到Spring中代码的优秀,即使是一个很复杂的逻辑,在Spring中也会被拆分为若干个小的逻辑,然后在每个函数中实现,使得每个函数的逻辑简单到我们能快速的理解,而不会像有些人开发的那样,将一大堆的逻辑都罗列在一个函数中,给后期维护文员造成巨大的困扰。


      同样,通过上面的函数,Spring又将任务进行了拆分,分成了获取所有增强器与增强器是否匹配两个功能点。


(1)寻找候选增强器


      在findCandidateAdvisors函数中完成的就是获取增强器的功能,AbstractAdvisorAutoProxyCreator类的findCandidateAdvisors函数:


1 protected List<Advisor> findCandidateAdvisors() {
2 Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
3 return this.advisorRetrievalHelper.findAdvisorBeans();
4 }

  上面函数调用了advisorRetrievalHelper类(package org.springframework.aop.framework.autoproxy)的findAdvisorBeans函数,进入函数:


1 public List<Advisor> findAdvisorBeans() {
2 //cachedAdvisorBeanNames是advisor名称的缓存
3 String[] advisorNames = this.cachedAdvisorBeanNames;
4 //如果cachedAdvisorBeanNames为空,则到容器中查找,并设置缓存,后续直接使用缓存即可
5 if (advisorNames == null) {
6 // Do not initialize FactoryBeans here: We need to leave all regular beans
7 // uninitialized to let the auto-proxy creator apply to them!
8 //从容器中查找Advisor类型的bean的名称
9 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
10 this.beanFactory, Advisor.class, true, false);
11 this.cachedAdvisorBeanNames = advisorNames;
12 }
13 if (advisorNames.length == 0) {
14 return new ArrayList<>();
15 }
16
17 List<Advisor> advisors = new ArrayList<>();
18 //遍历advisorNames
19 for (String name : advisorNames) {
20 if (isEligibleBean(name)) {
21 //忽略郑州创建中的advisor bean
22 if (this.beanFactory.isCurrentlyInCreation(name)) {
23 if (logger.isTraceEnabled()) {
24 logger.trace("Skipping currently created advisor "" + name + """);
25 }
26 }
27 else {
28 try {
29 //调用getBean方法从容器中获取名称为name的bean,并将bean添加到advisors中
30 advisors.add(this.beanFactory.getBean(name, Advisor.class));
31 }
32 catch (BeanCreationException ex) {
33 Throwable rootCause = ex.getMostSpecificCause();
34 if (rootCause instanceof BeanCurrentlyInCreationException) {
35 BeanCreationException bce = (BeanCreationException) rootCause;
36 String bceBeanName = bce.getBeanName();
37 if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
38 if (logger.isTraceEnabled()) {
39 logger.trace("Skipping advisor "" + name +
40 "" with dependency on currently created bean: " + ex.getMessage());
41 }
42 // Ignore: indicates a reference back to the bean we"re trying to advise.
43 // We want to find advisors other than the currently created bean itself.
44 continue;
45 }
46 }
47 throw ex;
48 }
49 }
50 }
51 }
52 return advisors;
53 }

      对于上面的函数,你看懂其中的奥秘了吗?首先是通过BeanFactoryUtils类提供的工具方法获取所有对应的Advisor.class的类。


1 //从容器中查找Advisor类型的bean的名称
2 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
3 this.beanFactory, Advisor.class, true, false);

      进入BeanFactoryUtils类(package org.springframework.beans.factory)的beanNamesForTypeIncludingAncestors函数:


1 public static String[] beanNamesForTypeIncludingAncestors(
2 ListableBeanFactory lbf, ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
3
4 Assert.notNull(lbf, "ListableBeanFactory must not be null");
5 String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
6 if (lbf instanceof HierarchicalBeanFactory) {
7 HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
8 if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
9 String[] parentResult = beanNamesForTypeIncludingAncestors(
10 (ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
11 result = mergeNamesWithParent(result, parentResult, hbf);
12 }
13 }
14 return result;
15 }

      从上面代码可以看出,实际调用的是ListableBeanFactory类提供的getBeanNamesForType函数。


      而当我们知道增强器在容器中beanName时,获取增强器已经不是问题了,在BeanFactory中提供了这样的方法,可以帮助我们快速的定位对应的bean实例。


<T> T getBean(String name, Class<T> requiredType) throws BeansException;

  或许你已经忘了之前留下的悬念,在我们讲解自定义标签时曾经注册了一个类型为BeanFactoryTransactionAttributeSourceAdvisor的bean,(package org.springframework.transaction.config 包中的AnnotationDrivenBeanDefinitionParser类的内部类AopAutoProxyConfigurer类中),而在此bean总我们又注入另外两个Bean,那么此时这个Bean就会被开始使用了。因为BeanFactoryTransactionAttributeSourceAdvisor同样也实现了Advisor接口,那么在获取所有增强器是自然也会将此bean提取出来并随着其他增强器一起在 后续的步骤中被织入代理。


(2)候选增强器中寻找到匹配项


  当找出对应的增强后,接下来的任务就是看这些增强是否与对应的class匹配了,当然不只是class,class内部的方法如果匹配也可以通过验证,AbstractAdvisorAutoProxyCreator类(packageorg.springframework.aop.framework.autoproxy)的findAdvisorsThatCanApply函数:


1 protected List<Advisor> findAdvisorsThatCanApply(
2 List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
3
4 ProxyCreationContext.setCurrentProxiedBeanName(beanName);
5 try {
6 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
7 }
8 finally {
9 ProxyCreationContext.setCurrentProxiedBeanName(null);
10 }
11 }
  其中又调用了AopUtils类(package org.springframework.aop.support)的findAdvisorsThatCanApply函数:
1 public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
2 if (candidateAdvisors.isEmpty()) {
3 return candidateAdvisors;
4 }
5 List<Advisor> eligibleAdvisors = new ArrayList<>();
6 for (Advisor candidate : candidateAdvisors) {
7 //刷选IntroductionAdvisor引介类型的通知器
8 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
9 eligibleAdvisors.add(candidate);
10 }
11 }
12 boolean hasIntroductions = !eligibleAdvisors.isEmpty();
13 for (Advisor candidate : candidateAdvisors) {
14 if (candidate instanceof IntroductionAdvisor) {
15 //引介增强已经处理
16 continue;
17 }
18 //刷选普通类型的通知器
19 if (canApply(candidate, clazz, hasIntroductions)) {
20 eligibleAdvisors.add(candidate);
21 }
22 }
23 return eligibleAdvisors;
24 }
  上面函数调用了该类中的canApply函数:
1 public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
2 if (advisor instanceof IntroductionAdvisor) {
3 /*
4 * 从通知器中获取类型过滤器 ClassFilter,并调用 matchers 方法进行匹配。
5 * ClassFilter 接口的实现类 AspectJExpressionPointcut 为例,该类的
6 * 匹配工作由 AspectJ 表达式解析器负责,具体匹配细节这个就没法分析了,我
7 * AspectJ 表达式的工作流程不是很熟
8 */
9 return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
10 }
11 else if (advisor instanceof PointcutAdvisor) {
12 PointcutAdvisor pca = (PointcutAdvisor) advisor;
13 // 对于普通类型的通知器,这里继续调用重载方法进行筛选
14 return canApply(pca.getPointcut(), targetClass, hasIntroductions);
15 }
16 else {
17 // It doesn"t have a pointcut so we assume it applies.
18 return true;
19 }
20 }

  当前我们分析的是对于UserService是否适用于此增强方法,那么当前的advisor就是之前查找出来的类型为BeanFactoryTransactionAttributeSourceAdvisor的bean实例,而通过类的层次几个我们又知道:BeanFactoryTransactionAttributeSourceAdvisor间接实现了PointAdvisor(BeanFactoryTransactionAttributeSourceAdvisor继承自AbstractBeanFactoryPointcutAdvisor继承自AbstractPointcutAdvisor继承自PointcutAdvisor)。因此,在canApply函数中的第二个if判断时就会通过判断,会将BeanFactoryTransactionAttributeSourceAdvisor中的getPointcut()方法返回值作为参数继续调用canApply方法,而getPointcut ()方法返回的是TransactionAttributeSourcePointcut类型的实例。对于transactionAttributeSource这个属性大家还有印象吗?这是在解析自定义标签时注入进去的。BeanFactoryTransactionAttributeSourceAdvisor类中代码:


1 private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
2 @Override
3 @Nullable
4 protected TransactionAttributeSource getTransactionAttributeSource() {
5 return transactionAttributeSource;
6 }
7 };

  那么使用TransactionAttributeSourcePointcut类型的实例作为函数参数继续跟踪canApply,AopUtils类(package org.springframework.aop.support)的CanApply函数:


1 public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
2 Assert.notNull(pc, "Pointcut must not be null");
3 //使用 ClassFilter 匹配 class
4 if (!pc.getClassFilter().matches(targetClass)) {
5 return false;
6 }
7
8 MethodMatcher methodMatcher = pc.getMethodMatcher();
9 if (methodMatcher == MethodMatcher.TRUE) {
10 // No need to iterate the methods if we"re matching any method anyway...
11 return true;
12 }
13
14 IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
15 if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
16 introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
17 }
18
19
20 /*
21 * 查找当前类及其父类(以及父类的父类等等)所实现的接口,由于接口中的方法是 public,
22 * 所以当前类可以继承其父类,和父类的父类中所有的接口方法
23 */
24 Set<Class<?>> classes = new LinkedHashSet<>();
25 if (!Proxy.isProxyClass(targetClass)) {
26 classes.add(ClassUtils.getUserClass(targetClass));
27 }
28 classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
29
30 for (Class<?> clazz : classes) {
31 // 获取当前类的方法列表,包括从父类中继承的方法
32 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
33 for (Method method : methods) {
34 // 使用 methodMatcher 匹配方法,匹配成功即可立即返回
35 if (introductionAwareMethodMatcher != null ?
36 introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
37 methodMatcher.matches(method, targetClass)) {
38 return true;
39 }
40 }
41 }
42
43 return false;
44 }

      通过上面函数大致可以理清大体脉络,首先获取对应类的所有接口并连同类本身一起遍历,遍历过程中又对类中的方法再次遍历,一旦匹配成功便认为这个类适用于当前的增强器。


      到这里我们不禁会有疑问,对于事务的配置不仅仅局限于在函数上配置,我们都知道,在类或接口上的配置可以延续到类中的每个函数。那么,如果针对每个函数进行检测,在类本身上配置的事务属性岂不是检测不到了吗?带着这个疑问,我们继续探求matcher方法。


      做匹配的时候methodMatcher.matches(method, targetClass)会使用TransactionAttributeSourcePointcut类(package org.springframework.transaction.interceptor)的matches方法。


1 public boolean matches(Method method, Class<?> targetClass) {
2 //自定义标签解析时注入
3 TransactionAttributeSource tas = getTransactionAttributeSource();
4 return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
5 }

  此时的tas表示AnnotationTransactionAttributeSource类型,而AnnotationTransactionAttributeSource类型的getTransactionAttribute方法如下(该方法在其父类AbstractFallbackTransactionAttributeSource中)。AbstractFallbackTransactionAttributeSource类(package org.springframework.transaction.interceptor)的getTransactionAttribute方法


1 public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
2 if (method.getDeclaringClass() == Object.class) {
3 return null;
4 }
5
6 // First, see if we have a cached value.
7 Object cacheKey = getCacheKey(method, targetClass);
8 TransactionAttribute cached = this.attributeCache.get(cacheKey);
9 if (cached != null) {
10 // Value will either be canonical value indicating there is no transaction attribute,
11 // or an actual transaction attribute.
12 if (cached == NULL_TRANSACTION_ATTRIBUTE) {
13 return null;
14 }
15 else {
16 return cached;
17 }
18 }
19 else {
20 // We need to work it out.
21 TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
22 // Put it in the cache.
23 if (txAttr == null) {
24 this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
25 }
26 else {
27 String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
28 if (txAttr instanceof DefaultTransactionAttribute) {
29 ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
30 }
31 if (logger.isTraceEnabled()) {
32 logger.trace("Adding transactional method "" + methodIdentification + "" with attribute: " + txAttr);
33 }
34 this.attributeCache.put(cacheKey, txAttr);
35 }
36 return txAttr;
37 }
38 }

      很遗憾,在getTransactionAttribute函数中并没有找到我们想要的代码,这里是指常规的一贯的套路。尝试从缓存加载,如果对应信息没有被缓存的话,工作又委托给了computeTransactionAttribute函数,在computeTransactionAttribute函数中我们看到了事务标签的提取过程。AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法:


1 protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
2 // Don"t allow no-public methods as required.
3 if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
4 return null;
5 }
6
7 // The method may be on an interface, but we need attributes from the target class.
8 // If the target class is null, the method will be unchanged.
9 //method代表接口中的方法,specificMethod代表类中的方法
10 Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
11
12 // First try is the method in the target class.
13 //查看方法中是否存在事务声明
14 TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
15 if (txAttr != null) {
16 return txAttr;
17 }
18
19 // Second try is the transaction attribute on the target class.
20 //查看方法所在的类是否存在事务声明
21 txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
22 if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
23 return txAttr;
24 }
25
26 //如果存在接口,则到接口中去寻找
27 if (specificMethod != method) {
28 // Fallback is to look at the original method.
29 //查找接口方法
30 txAttr = findTransactionAttribute(method);
31 if (txAttr != null) {
32 return txAttr;
33 }
34 // Last fallback is the class of the original method.
35 //到接口的类中去寻找
36 txAttr = findTransactionAttribute(method.getDeclaringClass());
37 if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
38 return txAttr;
39 }
40 }
41
42 return null;
43 }

      对于事物属性的获取规则相信大家已经很清楚,如果方法中存在事务属性,则使用方法上的属性,否则使用方法所在的类上的属性,如果方法所在类的属性上还是没有搜寻到对应的事务属性,那么再搜寻接口中的方法,再没有的话,最后尝试搜寻接口的类上面的声明。对于函数computeTransactionAttribute中的逻辑与我们所认识的规则并无差别,但是上面函数中并没有真正的去做搜寻事务属性的逻辑,而是搭建了一个执行框架,将搜寻事务属性的任务委托给了findTransactionAttribute方法去执行。AnnotationTransactionAttributeSource类(package org.springframework.transaction.annotation)的findTransactionAttribute方法:


1 protected TransactionAttribute findTransactionAttribute(Method method) {
2 return determineTransactionAttribute(method);
3 }

   上面函数调用了本类中的determineTransactionAttribute方法:


1 protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
2 for (TransactionAnnotationParser parser : this.annotationParsers) {
3 TransactionAttribute attr = parser.parseTransactionAnnotation(element);
4 if (attr != null) {
5 return attr;
6 }
7 }
8 return null;
9 }

      this.annotationParsers是在当前类AnnotationTransactionAttributeSource初始化的时候初始化的,其中的值被加入了SpringTransactionAnnotationParser,也就是当进行属性获取的时候其实是使用SpringTransactionAnnotationParser类(package org.springframework.transaction.annotation)的parseTransactionAnnotation方法进行解析的:


1 public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
2 AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
3 element, Transactional.class, false, false);
4 if (attributes != null) {
5 return parseTransactionAnnotation(attributes);
6 }
7 else {
8 return null;
9 }
10 }

  至此,我们终于看到了想看到的获取注解标记的代码。首先会判断当前的类是否含有Transactional注解,这是事务属性的基础,当然如果有的话会继续调用SpringTransactionAnnotationParser类的parseTransactionAnnotation方法解析详细的属性:


1 protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
2 RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
3
4 //解析propagation
5 Propagation propagation = attributes.getEnum("propagation");
6 rbta.setPropagationBehavior(propagation.value());
7 //解析isolation
8 Isolation isolation = attributes.getEnum("isolation");
9 rbta.setIsolationLevel(isolation.value());
10 //解析timeout
11 rbta.setTimeout(attributes.getNumber("timeout").intValue());
12 //解析readOnly
13 rbta.setReadOnly(attributes.getBoolean("readOnly"));
14 //解析value
15 rbta.setQualifier(attributes.getString("value"));
16
17 //解析rollbackFor
18 List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
19 for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
20 rollbackRules.add(new RollbackRuleAttribute(rbRule));
21 }
22 //解析rollbackForClassName
23 for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
24 rollbackRules.add(new RollbackRuleAttribute(rbRule));
25 }
26 //解析noRollbackFor
27 for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
28 rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
29 }
30 //noRollbackForClassName
31 for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
32 rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
33 }
34 rbta.setRollbackRules(rollbackRules);
35
36 return rbta;
37 }

      上面方法中实现了对对应类或者方法的事务属性解析,你会在这个类中看到任何你常用或者不常用的属性提取。


      至此,我们终于完成了事务标签的解析。我们是不是分析得太远了,似乎已经忘记了从哪里开始了。再回顾一下,我们现在的任务是找出某个增强器是否适合于对应的类,而是否匹配的关键则在于是否从指定的类或类中的方法中找到对应的事务属性,现在,我们以UserServiceImple为例,已经在它的接口UserService中找到了事务属性,所以,它是与事务增强器匹配的,也就是它会被事务功能修饰。


      至此,事务功能的初始化工作便结束了,当判断某个bean适用于事务增强时,也就是适用于增强器BeanFactoryTransactionAttributeSourceAdvisor。没错,还是这个类,所以说,在自定义标签解析时,注入的类成为了整个事务功能的基础。


      BeanFactoryTransactionAttributeSourceAdvisor作为Advisor的实现类,自然要遵从Advisor的处理方式,当代理被调用时会调用这个类的增强方法,也就是此bean的Advisor,又因为在解析事务定义标签时我们把TransactionInterceptor类型的bean注入到了BeanFactoryTransactionAttributeSourceAdvisor中,所以,在调用事务增强器增强的代理类时会首先执行TransactionInterceptor进行增强,同时,也就是TransactionInterceptor类的invoke方法中完成了整个事务的逻辑。


 


三、事务增强器


      TransactionInterceptor支撑着整个事务功能的架构,逻辑还是相对复杂的,那么现在我们切入正题来分析此拦截器是如何实现事务特性的。TransactionInterceptor类(package org.springframework.transaction.interceptor)继承自MethodInterceptor,所以调用该类是从其invoke方法开始的:


1 public Object invoke(MethodInvocation invocation) throws Throwable {
2 // Work out the target class: may be {@code null}.
3 // The TransactionAttributeSource should be passed the target class
4 // as well as the method, which may be from an interface.
5 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
6
7 // Adapt to TransactionAspectSupport"s invokeWithinTransaction...
8 return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
9 }

      其中又调用了其父类TransactionAspectSupport(package org.springframework.transaction.interceptor)的invokeWithinTransaction方法。


1 protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
2 final InvocationCallback invocation) throws Throwable {
3
4 // If the transaction attribute is null, the method is non-transactional.
5 //获取对应事务属性
6 TransactionAttributeSource tas = getTransactionAttributeSource();
7 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
8 //获取BeanFactory中的TransactionManager
9 final TransactionManager tm = determineTransactionManager(txAttr);
10
11 if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
12 ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
13 if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
14 throw new TransactionUsageException(
15 "Unsupported annotated transaction on suspending function detected: " + method +
16 ". Use TransactionalOperator.transactional extensions instead.");
17 }
18 ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
19 if (adapter == null) {
20 throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
21 method.getReturnType());
22 }
23 return new ReactiveTransactionSupport(adapter);
24 });
25 return txSupport.invokeWithinTransaction(
26 method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
27 }
28
29 PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
30 //构造方法唯一标识(类.方法 如service.UserServiceImpl.save)
31 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
32
33 //声明式事务处理
34 if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
35 // Standard transaction demarcation with getTransaction and commit/rollback calls.
36 //创建TransactionInfo
37 TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
38
39 Object retVal;
40 try {
41 // This is an around advice: Invoke the next interceptor in the chain.
42 // This will normally result in a target object being invoked.
43 //执行被增强方法
44 retVal = invocation.proceedWithInvocation();
45 }
46 catch (Throwable ex) {
47 // target invocation exception
48 //异常回滚
49 completeTransactionAfterThrowing(txInfo, ex);
50 throw ex;
51 }
52 finally {
53 //清除信息
54 cleanupTransactionInfo(txInfo);
55 }
56
57 if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
58 // Set rollback-only in case of Vavr failure matching our rollback rules...
59 TransactionStatus status = txInfo.getTransactionStatus();
60 if (status != null && txAttr != null) {
61 retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
62 }
63 }
64
65 //提交事务
66 commitTransactionAfterReturning(txInfo);
67 return retVal;
68 }
69
70 else {
71 final ThrowableHolder throwableHolder = new ThrowableHolder();
72
73 // It"s a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
74 //编程式事务处理
75 try {
76 Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
77 TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
78 try {
79 Object retVal = invocation.proceedWithInvocation();
80 if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
81 // Set rollback-only in case of Vavr failure matching our rollback rules...
82 retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
83 }
84 return retVal;
85 }
86 catch (Throwable ex) {
87 if (txAttr.rollbackOn(ex)) {
88 // A RuntimeException: will lead to a rollback.
89 if (ex instanceof RuntimeException) {
90 throw (RuntimeException) ex;
91 }
92 else {
93 throw new ThrowableHolderException(ex);
94 }
95 }
96 else {
97 // A normal return value: will lead to a commit.
98 throwableHolder.throwable = ex;
99 return null;
100 }
101 }
102 finally {
103 cleanupTransactionInfo(txInfo);
104 }
105 });
106
107 // Check result state: It might indicate a Throwable to rethrow.
108 if (throwableHolder.throwable != null) {
109 throw throwableHolder.throwable;
110 }
111 return result;
112 }
113 catch (ThrowableHolderException ex) {
114 throw ex.getCause();
115 }
116 catch (TransactionSystemException ex2) {
117 if (throwableHolder.throwable != null) {
118 logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
119 ex2.initApplicationException(throwableHolder.throwable);
120 }
121 throw ex2;
122 }
123 catch (Throwable ex2) {
124 if (throwableHolder.throwable != null) {
125 logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
126 }
127 throw ex2;
128 }
129 }
130 }

      从上面的函数中,我们尝试整理下事务处理的脉络,在Spring中支持两种事务处理的方式,分别是声明式事务处理和编程式事务处理,两者相对于开发人员来讲差别很大,但是对于Spring中的实现来讲,大同小异。在invoke中我们也可以看到这两种方式的实现。考虑到对事务的应用比声明式的事务处理使用起来方便,也相对流行些,我们就此种方式进行分析。对于声明式的事务处理主要有以下几个步骤。


      ① 获取事务的属性。


      对于事务处理来说,最基础或者最首要的工作便是获取事务的属性了。这是支撑整个事务功能的基石。如果没有事务属性,其他功能也就无从谈起,在分析事务准备阶段我们已经分析了事务属性提取的功能,大家应该有所了解。


      ② 加载配置中配置的TransactionManager。


      ③ 不同的事务处理方式使用不同的逻辑。


      对于声明式事务的处理与编程式事务的处理,第一点区别在于事务属性上,因为编程式的事务处理是不需要有事务属性的,第二点区别就是在TransactionManager上,CallbackPreferringPlatformTransactionManager实现了PlatformTransactionManager接口,暴露出一个方法用于执行事务处理中的回调。所以,这两种方式都可以用作事务处理方式的判断。


      ④ 在目标方法执行前获取事务并收集事务信息。


      事务信息与事务属性并不相同,也就是TransactionInfo与TransactionAttribute并不相同,TransactionInfo包含TransactionAttribute信息,但是,除了TransactionAttribute外还有其他事务信息,例如PlatformTransactionManager以及TransactionStatus相关信息。


      ⑤ 执行目标方法。


      ⑥ 一旦出现异常,尝试异常处理。


      ⑦ 提交事务前的事务信息清除。


      ⑧ 提交事务。


      上面的步骤分析旨在让大家对事务功能与步骤有个大致的了解,具体的功能还需要详细地分析。


(一)创建事务


      我们先分析事务创建的过程。TransactionAspectSupport类(package org.springframework.transaction.interceptor)的createTransactionIfNecessary方法:


1 protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
2 @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
3
4 // If no name specified, apply method identification as transaction name.
5 //如果没有名称指定则使用方法唯一标识,并使用DelegatingTransactionAttribute封装txAttr
6 if (txAttr != null && txAttr.getName() == null) {
7 txAttr = new DelegatingTransactionAttribute(txAttr) {
8 @Override
9 public String getName() {
10 return joinpointIdentification;
11 }
12 };
13 }
14
15 TransactionStatus status = null;
16 if (txAttr != null) {
17 if (tm != null) {
18 //获取TransactionStatus
19 status = tm.getTransaction(txAttr);
20 }
21 else {
22 if (logger.isDebugEnabled()) {
23 logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
24 "] because no transaction manager has been configured");
25 }
26 }
27 }
28 //根据指定的属性与status准备一个TransactionInfo
29 return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
30 }

      对于createTransactionIfNecessary函数主要做了这样几件事情。


      ① 使用DelegatingTransactionAttribute封装传入的TransactionAttribute实例。


      对于传入的TransactionAttribute类型的参数txAttr,当前的实际类型是RuleBasedTransactionAttribute,是由获取事务属性时生成的,主要用于数据承载,而这里之所以使用DelegatingTransactionAttribute进行封装,当时是提供了更多的功能。


      ② 获取事务


      事务处理当然是以事务为核心,那么获取事务就是最重要的事情。


      ③ 构建事务信息


      根据之前几个步骤获取的信息构建TransactionInfo并返回。


      我们分别对以上步骤进行详细的解析。


(1)获取事务


      Spring中使用getTransaction来处理事务的准备工作,包括事务获取以及信息的构建。getTransaction函数在实现PlatformTransactionManager接口的AbstractPlatformTransactionManager抽象类(package org.springframework.transaction.support)中给出了具体实现方法:


1 public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
2 throws TransactionException {
3
4 // Use defaults if no transaction definition given.
5 TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
6
7 Object transaction = doGetTransaction();
8 boolean debugEnabled = logger.isDebugEnabled();
9
10 //判断当前线程是否存在事务,判读依据为当前线程记录的连接不为空且连接中(connectionHolder)中的transactionActive属性不为空
11 if (isExistingTransaction(transaction)) {
12 // Existing transaction found -> check propagation behavior to find out how to behave.
13 //当前线程已经存在事务
14 return handleExistingTransaction(def, transaction, debugEnabled);
15 }
16
17 // Check definition settings for new transaction.
18 //事务超时设置验证
19 if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
20 throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
21 }
22
23 // No existing transaction found -> check propagation behavior to find out how to proceed.
24 //如果当前线程不存在事务,但是PropagationBehavior却被声明为PROPAGATION_MANDATORY抛出异常
25

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/xxkj/p/14287924.html

随机推荐

一条SQL查询语句时如何执行的(一)

一、Mysql的逻辑架构图大体上Mysql可分为Server层和存储引擎层两部分。Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数...

香山上的麻雀1008 阅读(383)

蓝桥杯竞赛练习1

蓝桥练习2021年1月13日进行了蓝桥杯官网里面的入门训练斐波那契数列圆的面积序列求和A+B问题基础练习里面的:数列排序十六进制转八进制由于不是VIP账户,所以部分...

weixin_45941222 阅读(939)

数的三次方根(浮点二分)

数的三次方根(浮点二分)

题目思路:二分找到某个数的三次方等于xAc代码:#include<iostream>usingnamespacestd;intmain(){doublex;ci...

dosafdc 阅读(684)

windows下Redis的安装和使用

Readis安装地址:https://github.com/MicrosoftArchive/redis/releases1、要安装Redis,首先要获取安装包。Windo...

邵_金波 阅读(133)

网络存储空间_服务器的数据存储解决方案,磁盘阵列和网络存储

网络存储空间_服务器的数据存储解决方案,磁盘阵列和网络存储

数据存储解决方案需要以电子方式存储数据并使其具有机器可读性。这些解决方案的目的是使数据存储和访问变得简单可靠。数字数据在无纸化数据管理方面表现优异。磁盘/存储阵列包含通过专用存储硬件(如旋转和固态硬盘...

weixin_39524882 阅读(358)

《计量经济学》复习重点(敲黑板~)

【n】不用理会,是我自己的书的页数,可能会有不同哈!逢考必过!冲冲冲!导论1.计量经济学研究步骤【8】模型设定——确定变量和数学关...

大白要努力啊 阅读(531)