欢迎大家关注github.com/hsfxuebao,希望对大家有所协助,要是觉得能够的话费事给点一下Star哈

1. 事例(注解版)

  1. 引进依赖 build.gradle文件:
     dependencies {
         api(project(":spring-context"))
         api(project(":spring-aspects"))  //引进aop&切面模块
         api(project(":spring-jdbc"))  //引进jdbc模块
         // https://mvnrepository.com/artifact/c3p0/c3p0
         implementation group: 'c3p0', name: 'c3p0', version: '0.9.1.2'
         // https://mvnrepository.com/artifact/mysql/mysql-connector-java
         implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.18'
         // https://mvnrepository.com/artifact/org.projectlombok/lombok
         compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.14'
     }
    
  2. 注解版装备文件
@ComponentScan("com.hsf.spring.tx")
@Configuration
@EnableTransactionManagement
public class TxConfig {
   @Bean
   public DataSource dataSource() throws Exception {
      ComboPooledDataSource dataSource = new ComboPooledDataSource();
      dataSource.setUser("root");
      dataSource.setPassword("hsfxuebao");
      dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
      dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/spring_tx");
      return dataSource;
   }
   @Bean
   public JdbcTemplate jdbcTemplate() throws Exception {
      // Spring对@Configuration类会特殊处理,给容器中加组件的办法,多次调用都只是从容器中找组件
      return new JdbcTemplate(dataSource());
   }
   // 注册业务管理器
   @Bean
   public PlatformTransactionManager transactionManager() throws Exception {
      return new DataSourceTransactionManager(dataSource());
   }
}
  1. 实例类
@Repository
public class UserDao {
   @Autowired
   private JdbcTemplate jdbcTemplate;
   public void insert() {
      String sql = "INSERT INTO user(name,age) values(?,?)";
      String name = UUID.randomUUID().toString().substring(0, 5);
      jdbcTemplate.update(sql, name, 19);
   }
}
@Service
public class UserInfoService {
   public void test() {
      System.out.println("UserInfoService.test()");
   }
}
@Service
public class UserService {
   @Autowired
   private UserDao userDao;
   // 不主动注入,模仿空指针反常
   private UserInfoService userInfoService;
   @Transactional()
   public void insertUser() {
      userDao.insert();
      System.out.println("插入完结");
      // 模仿空指针反常
      userInfoService.test();
   }
}
  1. 测验类
public static void main(String[] args) {
   AnnotationConfigApplicationContext context =
         new AnnotationConfigApplicationContext(TxConfig.class);
   // 业务
   UserService userService = context.getBean(UserService.class);
   userService.insertUser();
}

2. @EnableTransactionManagement

咱们第1末节中开端业务管理很简单,运用 @EnableTransactionManagement 注解即可。那么也就说明 @EnableTransactionManagement 是咱们剖析的进口了。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
	boolean proxyTargetClass() default false;
	AdviceMode mode() default AdviceMode.PROXY;
	int order() default Ordered.LOWEST_PRECEDENCE;
}

很明显了@Import(TransactionManagementConfigurationSelector.class) 指向咱们去看 去看 TransactionManagementConfigurationSelector 的完结。

2.1 TransactionManagementConfigurationSelector

Spring5源码15-事务(AutoProxyRegistrar和ProxyTransactionManagementConfiguration)

能够看到,TransactionManagementConfigurationSelector 直接完结了 ImportSelector 接口,ImportSelector 会依据 selectImports 回来的字符串数组(一般是类的全路径名) 经过反射加载该类并注册到Spring容器中

所以咱们这儿必定来看一下 selectImports 办法了,ImportSelector#selectImports 的完结在其父类AdviceModeImportSelector#selectImports:

@Override
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 获取注解类型, 这儿是 EnableTransactionManagement
        Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
        Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
        // 解分出 @EnableTransactionManagement 注解的参数
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
        if (attributes == null) {
                throw new IllegalArgumentException(String.format(
                                "@%s is not present on importing class '%s' as expected",
                                annType.getSimpleName(), importingClassMetadata.getClassName()));
        }
        // 获取mode特点。EnableTransactionManagement 默许mode =  AdviceMode.PROXY
        AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
        // 调用 TransactionManagementConfigurationSelector#selectImports
        String[] imports = selectImports(adviceMode);
        if (imports == null) {
                throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
        }
        return imports;
}
...
        @Nullable
protected abstract String[] selectImports(AdviceMode adviceMode);

能够知道了 这儿是将 protected abstract String[] selectImports(AdviceMode adviceMode); 回来的值回来给 Spring。这儿咱们看看在 TransactionManagementConfigurationSelector 中的 selectImports(AdviceMode adviceMode) 办法的完结。

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		// 默许值 是 PROXY。个人猜测是经过 署理形式完结业务,假如是 ASPECTJ 则是经过 ASPECTJ的办法完结,AspectJ 需求独自引进编译
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}
	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}
}

到这儿就能够看到了,默许状况下,咱们引进了两个类,AutoProxyRegistrarProxyTransactionManagementConfiguration

  • AutoProxyRegistrar : 首要是注册了 InfrastructureAdvisorAutoProxyCreator 主动署理创立器。而 InfrastructureAdvisorAutoProxyCreator 的逻辑根本上和 Aop 的逻辑相同
  • ProxyTransactionManagementConfiguration : 注册了业务完结的中心 Bean,包括 BeanFactoryTransactionAttributeSourceAdvisorTransactionAttributeSourceTransactionInterceptor

3. AutoProxyRegistrar

AutoProxyRegistrar完结了 ImportBeanDefinitionRegistrar 接口,所以咱们要去看看他的registerBeanDefinitions 办法的完结。

AutoProxyRegistrar#registerBeanDefinitions 代码如下:

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean candidateFound = false;
        // 获取 当时类上的一切注解
        Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
        for (String annType : annTypes) {
                // 获取注解的一切特点
                AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
                if (candidate == null) {
                        continue;
                }
                // 获取mode、proxyTargetClass 特点
                Object mode = candidate.get("mode");
                Object proxyTargetClass = candidate.get("proxyTargetClass");
                if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
                                Boolean.class == proxyTargetClass.getClass()) {
                        candidateFound = true;
                        // 判别假如是 Proxy 形式,也便是默许形式,注册主动署理创立器
                        if (mode == AdviceMode.PROXY) {
                                AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                                // 假如需求署理方针列,则强制主动署理创立者运用类署理
                                if ((Boolean) proxyTargetClass) {
                                        AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                                        return;
                                }
                        }
                }
        }
        ... 省掉日志打印
}

在这儿咱们能够看到,registerBeanDefinitions 办法中解析了 业务注解,并注册了主动署理创立器。这儿主动署理创立器咱们在Aop 源码中提到过,是Aop 创立的中心。

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry) 这一步最首要的效果将主动署理创立器 InfrastructureAdvisorAutoProxyCreator 注册到了 Spring容器中。

经过数次跳转,咱们来到了 AopConfigUtils#registerOrEscalateApcAsRequired。其中这

public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
                "org.springframework.aop.config.internalAutoProxyCreator";
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
        // Set up the escalation list...
        // 业务运用
        APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
        APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
        // Spring aop 运用
        APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
....
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
                BeanDefinitionRegistry registry, @Nullable Object source) {
        return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
...
// 这儿的 cls 是 InfrastructureAdvisorAutoProxyCreator .class
private static BeanDefinition registerOrEscalateApcAsRequired(
                Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        // 假如有注册,则判别优先级,将优先级的高的保存
        // 假如现已纯在了主动署理创立器,且存在的主动署理创立器与现在的并不共同,那么需求依据优先级来判别到底要运用哪个
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
                BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
                if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                        int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                        int requiredPriority = findPriorityForClass(cls);
                        if (currentPriority < requiredPriority) {
                        // 改动bean所对应的className 特点
                                apcDefinition.setBeanClassName(cls.getName());
                        }
                }
                // 假如现已存在主动署理创立器,而且与将要创立的共同,那么无需再次创立
                return null;
        }
        RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
        beanDefinition.setSource(source);
        beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
        return beanDefinition;
}
...
// 能够看到,所谓的优先级次序实际上是在 APC_PRIORITY_LIST 调集的次序
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
                BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
                // 设置 proxyTargetClass 特点
                definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
        }
}
...
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
        if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
                BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
                // 设置 exposeProxy 特点
                definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
        }
}

到这儿咱们根本能够断定和 Aop 的逻辑根本相同了,只不过业务默许主动注入的主动署理创立器是 InfrastructureAdvisorAutoProxyCreator 类型。

留意:

  • 在AOP 中咱们知道 Aop创立的主动署理创立器类型是 AnnotationAwareAspectJAutoProxyCreator,而业务创立的类型是 InfrastructureAdvisorAutoProxyCreator
  • 这儿之所以 beanName (AUTO_PROXY_CREATOR_BEAN_NAME) 和 bean的类型并不相同,是因为这个beanName 特指内部的主动署理创立器,但是主动创立署理器会对应多种不同的完结办法。比如在默许的业务中,注入的bean类型却为InfrastructureAdvisorAutoProxyCreator,而AOP的完结却是 AnnotationAwareAspectJAutoProxyCreator
  • 关于主动署理创立器优先级的问题,咱们能够看到APC_PRIORITY_LIST 调集的次序,下标越大,优先级越高。因而能够得知优先级的次序应该是 InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator

3.1 InfrastructureAdvisorAutoProxyCreator

上面咱们能够知道,业务将主动署理创立器 InfrastructureAdvisorAutoProxyCreator 注册到了 Spring容器中。这儿就跟Aop 根本相同了,下面咱们来看看 InfrastructureAdvisorAutoProxyCreator 的内容

Spring5源码15-事务(AutoProxyRegistrar和ProxyTransactionManagementConfiguration)

能够看到 InfrastructureAdvisorAutoProxyCreator 并没有完结什么逻辑,首要逻辑在其父类 AbstractAutoProxyCreator 中。咱们在Aop 中提到过, AbstractAutoProxyCreator 是主动署理创立器的根底。绝大部分逻辑都是在其中完结的。(AbstractAutoProxyCreator 是AbstractAdvisorAutoProxyCreator 的父类,是 InfrastructureAdvisorAutoProxyCreator 的 “爷爷”类)。

public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
	@Nullable
	private ConfigurableListableBeanFactory beanFactory;
	@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		this.beanFactory = beanFactory;
	}
	@Override
	// 校验bean是否合格
	protected boolean isEligibleAdvisorBean(String beanName) {
		return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
				this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
	}
}

关于 AbstractAutoProxyCreator 的剖析量非常巨大,这儿不再重写剖析一遍,详细内容能够去看 AOP剖析文章的 AbstractAutoProxyCreator 部分。

3.2 业务中的 findCandidateAdvisors 办法

在这儿,咱们能够发现的是: Aop 的运用的是 AnnotationAwareAspectJAutoProxyCreator 主动署理创立器;业务运用的是InfrastructureAdvisorAutoProxyCreator主动署理创立器。而Aop署理创立的要害逻辑就主动署理创立器中。

咱们对比后两种主动署理创立器后,惊奇的发现,其实际逻辑根本共同。最大的不同之处在于,Aop 重写了 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors 办法。而业务并没有重写这一部分。所以业务调用的实际上是 AbstractAdvisorAutoProxyCreator#findCandidateAdvisors。即下面一部分

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

而Spring aop调用的则是重写后的 AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors:

@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.
        if (this.aspectJAdvisorsBuilder != null) {
                advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        }
        return advisors;
}

能够清楚的看到,Aop 的重写是加了this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 办法调用,也便是动态生成 Advisor 的部分。

关于 getAdvicesAndAdvisorsForBean 的源码剖析能够看Spring5源码13-AOP源码剖析(上)

到这儿咱们知道了 相较于 Aop 的 ,业务的 InfrastructureAdvisorAutoProxyCreator,不仅没有添加新逻辑(要害逻辑),还砍掉了动态生成Advisor 的逻辑。

3.3 为什么业务完结不需求动态生成Advisor 部分?

个人了解是因为因为事物的切入点并不像AOP那样如此多变。

  • 何为Aop的切入点多变,即Pointcut的定义规则由代码掌握,咱们经过 @Pointcut注解 能够定义一个匹配一切办法的切面,也能够定义一个匹配到指定的办法的切面,关于Spring来说,Spring无法经过一个 Advisor 满意许多Pointcut 条件,而为了满意这个条件所以需求经过代码来动态解析一切的Pointcut 来封装成一个一个的 Advisor,随后便能够经过 Advisor 来判别该办法是否满意某个 Advisor 的切入要求。
  • 而关于业务来说,启用业务的办法有必要要运用 @Transactional 来润饰办法(也能够润饰在类上,但这儿为了便利描绘直接说办法上,而且在类上运用更符合编程习气)。也便是说对Spring来说,判别一个办法是否启用业务的依据便是该办法上是否运用了 @Transactional 注解。也便是说,咱们仅需求一个 Advisor ,其判别条件是办法是否被@Transactional 注解润饰即可。而已然知道了Pointcut 条件,咱们就能够完结编写好满意这个逻辑的 Advisor,在Spring发动时分直接将这个条件的 Advisor 注入到容器中直接运用。
  • 综上,业务并不需求去动态注入 Advisor,而Spring aop 则需求动态注入。

经过上面的剖析,咱们判别,业务的Advisor 现已事前注入了,然后咱们回头看到TransactionManagementConfigurationSelector 中注入的另一个类 ProxyTransactionManagementConfiguration。在 ProxyTransactionManagementConfiguration 中果不其然发现了Advisor 的踪迹。

4. ProxyTransactionManagementConfiguration

ProxyTransactionManagementConfiguration 代码如下,并没有逻辑,便是将几个Bean注入的到容器中。不过这几个bean可都是要害bean,所以咱们需求对其中的bean进行剖析。

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			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(TransactionAttributeSource transactionAttributeSource) {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}
}

BeanFactoryTransactionAttributeSourceAdvisor : 业务的增强器,该办法是否开端业务,是否需求署理该类都在该类中判别

  • TransactionAttributeSource : 保存了业务相关的一些信息资源。
  • TransactionInterceptor : 业务拦截器,业务生成署理类时运用的署理拦截器,编写了业务的规则

4.1 BeanFactoryTransactionAttributeSourceAdvisor

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
	@Nullable
	private TransactionAttributeSource transactionAttributeSource;
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};
	/**
	 * Set the transaction attribute source which is used to find transaction
	 * attributes. This should usually be identical to the source reference
	 * set on the transaction interceptor itself.
	 * @see TransactionInterceptor#setTransactionAttributeSource
	 */
	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
		this.transactionAttributeSource = transactionAttributeSource;
	}
	/**
	 * Set the {@link ClassFilter} to use for this pointcut.
	 * Default is {@link ClassFilter#TRUE}.
	 */
	public void setClassFilter(ClassFilter classFilter) {
		this.pointcut.setClassFilter(classFilter);
	}
	@Override
	public Pointcut getPointcut() {
		return this.pointcut;
	}
}

这个依据上面的剖析,咱们能够知道这个是业务判别的中心,BeanFactoryTransactionAttributeSourceAdvisorAdvisor 子类,那么咱们能够知道其中有两个要害特点: Pointcut(判别是否能够效果于当时办法) 和 Advice(效果于当时办法的详细逻辑)。

经过 Aop文章的剖析咱们能够知道,Advisor 判别一个办法是否匹配,是经过其 Pointcut.matchs 特点来判别的。然后咱们经过上面的代码,发现其 Pointcut 的完结类是 TransactionAttributeSourcePointcut ,也便是说,一个办法是否需求运用业务,是经过 TransactionAttributeSourcePointcut#matches 办法判别的。

4.1.1. TransactionAttributeSourcePointcut

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
	protected TransactionAttributeSourcePointcut() {
		setClassFilter(new TransactionAttributeSourceClassFilter());
	}
	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		// 调用 TransactionAttributeSource.getTransactionAttribute办法来匹配
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}
	... 省掉一些无关代码
	/**
	 * Obtain the underlying TransactionAttributeSource (may be {@code null}).
	 * To be implemented by subclasses.
	 */
	@Nullable
	protected abstract TransactionAttributeSource getTransactionAttributeSource();
	/**
	 * {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}
	 * for filtering classes whose methods are not worth searching to begin with.
	 */
	private class TransactionAttributeSourceClassFilter implements ClassFilter {
		@Override
		public boolean matches(Class<?> clazz) {
			// 假如是一些根底类,则回来false
			if (TransactionalProxy.class.isAssignableFrom(clazz) ||
					PlatformTransactionManager.class.isAssignableFrom(clazz) ||
					PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
				return false;
			}
			// 调用 TransactionAttributeSource.isCandidateClass 办法来匹配
			TransactionAttributeSource tas = getTransactionAttributeSource();
			return (tas == null || tas.isCandidateClass(clazz));
		}
	}
}

Aop中咱们总结了 Pointcut 匹配的需求满意下面两个条件:

  • pc.getClassFilter().matches(targetClass) 回来true
  • pc.getMethodMatcher().matches(method, targetClass) 回来true

如下图,详细完结在 AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean) 中,这儿第二点不考虑,因为在这儿不会为True

Spring5源码15-事务(AutoProxyRegistrar和ProxyTransactionManagementConfiguration)

经过 TransactionAttributeSourcePointcut 的代码咱们能够发现,上面两个条件的要害 能够转换成

  • 调用 TransactionAttributeSource.isCandidateClass 办法来匹配 :TransactionAttributeSourceClassFilter#matches 中调用了该办法
  • 调用 TransactionAttributeSource.getTransactionAttribute办法来匹配

TransactionAttributeSource 正是咱们在 ProxyTransactionManagementConfiguration中注入的 AnnotationTransactionAttributeSource

4.2 AnnotationTransactionAttributeSource

经过上面的剖析,咱们知道了首要逻辑在 isCandidateClass getTransactionAttribute 办法中,也便是一个Bean 是否需求业务署理需求经过下面两个办法的校验。因而咱们下面来看看这两个办法的完结

4.2.1 AnnotationTransactionAttributeSource#isCandidateClass

isCandidateClass 首要是 判别是否是候选类,即当时的的注解解析器annotationParsers 是否能够解析当时类。annotationParsers 的初始化在其结构函数中,在初始化的进程中中添加了 SpringTransactionAnnotationParser,咱们后面的业务注解解析便是经过 SpringTransactionAnnotationParser 进行的解析。

这儿annotationParsers 有三种解析类型:

  • SpringTransactionAnnotationParser :即咱们默许的业务解析器,解析的注解是 org.springframework.transaction.annotation.Transactional
  • JtaTransactionAnnotationParser :解析的注解是 javax.transaction.Transactional
  • Ejb3TransactionAnnotationParser :解析的注解是 javax.ejb.TransactionAttribute
private final Set<TransactionAnnotationParser> annotationParsers;
...
public AnnotationTransactionAttributeSource() {
        this(true);
}
...
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
        this.publicMethodsOnly = publicMethodsOnly;
        // 能够看到,无论什么场景 SpringTransactionAnnotationParser 都是必定存在的解析器
        if (jta12Present || ejb3Present) {
                this.annotationParsers = new LinkedHashSet<>(4);
                this.annotationParsers.add(new SpringTransactionAnnotationParser());
                if (jta12Present) {
                        this.annotationParsers.add(new JtaTransactionAnnotationParser());
                }
                if (ejb3Present) {
                        this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
                }
        }
        else {
                this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
        }
}
@Override	
public boolean isCandidateClass(Class<?> targetClass) {
        for (TransactionAnnotationParser parser : this.annotationParsers) {
                // 这儿是SpringTransactionAnnotationParser  类型, SpringTransactionAnnotationParser#isCandidateClass 中判别了方针类是否存在  org.springframework.transaction.annotation.Transactional 注解
                if (parser.isCandidateClass(targetClass)) {
                        return true;
                }
        }
        return false;
}

SpringTransactionAnnotationParser#isCandidateClass 中判别了方针类是否存在 org.springframework.transaction.annotation.Transactional 注解,假如存在,这儿会回来true,经过校验

4.2.2 AbstractFallbackTransactionAttributeSource#getTransactionAttribute

getTransactionAttribute 办法的完结在其父类AbstractFallbackTransactionAttributeSource 中 完结的:

// 获取业务特点,假如
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        // 判别声明类是否是 Object 
        if (method.getDeclaringClass() == Object.class) {
                return null;
        }
        // First, see if we have a cached value.
        // 测验从缓冲中获取
        Object cacheKey = getCacheKey(method, targetClass);
        TransactionAttribute cached = this.attributeCache.get(cacheKey);
        if (cached != null) {
                // Value will either be canonical value indicating there is no transaction attribute,
                // or an actual transaction attribute.
                if (cached == NULL_TRANSACTION_ATTRIBUTE) {
                        return null;
                }
                else {
                        return cached;
                }
        }
        else {
                // We need to work it out.
                // 没有缓存,则开端解析
                TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
                // Put it in the cache.
                // 获取
                if (txAttr == null) {
                        // 放入缓存中
                        this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
                }
                else {
                        // 获取适宜的办法称号	
                        String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
                        if (txAttr instanceof DefaultTransactionAttribute) {
                                ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
                        }
                        if (logger.isTraceEnabled()) {
                                logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
                        }
                        this.attributeCache.put(cacheKey, txAttr);
                }
                return txAttr;
        }
}
...	
// 解析业务注解特点
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        // Don't allow no-public methods as required.
        // 假如只允许解析public 办法 && 当时办法不是 publissh
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
                return null;
        }
        // The method may be on an interface, but we need attributes from the target class.
        // If the target class is null, the method will be unchanged.
        // method 代表接口中的办法,specificMethod  办法代表完结类中的办法
        Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
        // First try is the method in the target class.
        // 寻觅完结类办法的业务特点,即类办法是否有声明业务特点
        TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
        if (txAttr != null) {
                return txAttr;
        }
        // Second try is the transaction attribute on the target class.
        // 在完结类上是否有业务特点的声明
        txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                return txAttr;
        }
        // 假如存在接口办法,则从接口办法中测验去获取业务特点
        if (specificMethod != method) {
                // Fallback is to look at the original method.
                txAttr = findTransactionAttribute(method);
                if (txAttr != null) {
                        return txAttr;
                }
                // Last fallback is the class of the original method.
                txAttr = findTransactionAttribute(method.getDeclaringClass());
                if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                        return txAttr;
                }
        }
        // 都没得到则回来没有得到
        return null;
}

这儿的逻辑仍是很清楚的

  • 从完结类办法上获取业务注解,若获取到则回来
  • 从完结类上获取业务注解,若获取到则回来
  • 假如存在接口办法,则从接口办法中获取业务注解,若获取到则回来
  • 若仍未获取到,则回来null,以为当时办法没有被注解润饰

AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method)在上面的代码中,咱们留意到一个办法 findTransactionAttribute。上面代码便是经过 findTransactionAttribute 办法来寻觅业务注解特点的。而findTransactionAttribute 的完结在 AnnotationTransactionAttributeSource 中。其完结代码如下

protected TransactionAttribute findTransactionAttribute(Method method) {
        return determineTransactionAttribute(method);
}
...
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
        for (TransactionAnnotationParser parser : this.annotationParsers) {
                TransactionAttribute attr = parser.parseTransactionAnnotation(element);
                if (attr != null) {
                        return attr;
                }
        }
        return null;
}

能够看到 AnnotationTransactionAttributeSource 中获取 业务注解是经过 TransactionAnnotationParser#parseTransactionAnnotation办法去解析的,而一开端咱们就说过annotationParsers 在结构函数中添加了SpringTransactionAnnotationParser。咱们来看看 SpringTransactionAnnotationParser 进行了怎么样的解析。到这儿,咱们终于看到了业务注解的描绘,这儿便是解析业务注解的各种特点信息了.

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
        // 获取业务注解的特点信息
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                        element, Transactional.class, false, false);
        if (attributes != null) {
                return parseTransactionAnnotation(attributes);
        }
        else {
                return null;
        }
}
....
// 解析业务注解,并回来
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
        RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
        // 解析各种特点信息
        Propagation propagation = attributes.getEnum("propagation");
        rbta.setPropagationBehavior(propagation.value());
        Isolation isolation = attributes.getEnum("isolation");
        rbta.setIsolationLevel(isolation.value());
        rbta.setTimeout(attributes.getNumber("timeout").intValue());
        rbta.setReadOnly(attributes.getBoolean("readOnly"));
        rbta.setQualifier(attributes.getString("value"));
        List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
        for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
                rollbackRules.add(new RollbackRuleAttribute(rbRule));
        }
        for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
                rollbackRules.add(new RollbackRuleAttribute(rbRule));
        }
        for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
                rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
        }
        for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
                rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
        }
        rbta.setRollbackRules(rollbackRules);
        return rbta;
}

咱们的剖析到这儿,就现已能够知道了Spring 中对业务注解的解析进程,逻辑根本和 Spring Aop 类似。

@EnableTransactionManagement 经过引进 TransactionManagementConfigurationSelector 注册了 AutoProxyRegistrarProxyTransactionManagementConfiguration 两个类。

  • AutoProxyRegistrar 中注册了 InfrastructureAdvisorAutoProxyCreator 主动署理创立器 InfrastructureAdvisorAutoProxyCreator 中拦截bean的创立进程,经过 BeanFactoryTransactionAttributeSourceAdvisor 来判别bean中是否有业务注解,有则进行署理。 在上面的逻辑中,咱们好像没有发现Spring业务署理的详细进程,实际上署理的进程是在 TransactionInterceptor 中。

4.3 TransactionInterceptor

在 Aop 的剖析文章中,咱们知道了无论是 Jdk署理仍是 Cglib署理,其增强完结都是调用 Advisor 中的Advice 完结。BeanFactoryTransactionAttributeSourceAdvisor 作为 Advisor 的完结类,天然要遵从 Advisor 的处理办法,当署理被调用时会调用这个类的增强办法,也便是此bean 的Advice ,而在解析业务标签是,咱们把 TransactionInterceptor 注入到了 BeanFactoryTransactionAttributeSourceAdvisor 中,所以调用业务增强器增强署理类的时会首先履行TransactionInterceptor 进行增强,同时也便是 TransactionInterceptor#invoke 完结了整个业务的逻辑。

所以咱们这儿天然要看 TransactionInterceptor#invoke 办法。

public Object invoke(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...
   // todo 在业务润饰下履行办法
   return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
      @Override
      @Nullable
      public Object proceedWithInvocation() throws Throwable {
         return invocation.proceed();
      }
      @Override
      public Object getTarget() {
         return invocation.getThis();
      }
      @Override
      public Object[] getArguments() {
         return invocation.getArguments();
      }
   });
}

能够看到中心逻辑都在 invokeWithinTransaction 办法中,这儿调用的 invokeWithinTransaction 办法 实际是TransactionAspectSupport#invokeWithinTransaction办法。所以下面咱们来看看 TransactionAspectSupport#invokeWithinTransaction 办法的详细完结

TransactionAspectSupport#invokeWithinTransaction
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
                final InvocationCallback invocation) throws Throwable {
        // If the transaction attribute is null, the method is non-transactional.
        // 获取业务数据源,这儿获取的数据源便是在  TransactionInterceptor 注入的时分的设置的特点transactionAttributeSource = AnnotationTransactionAttributeSource。
        // 在 ProxyTransactionManagementConfiguration 中完结	
        TransactionAttributeSource tas = getTransactionAttributeSource();
        // 1. 获取对应的业务特点
        final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
        // 2. 获取一个适宜的 TransactionManager 
        final TransactionManager tm = determineTransactionManager(txAttr);
        // 3. 关于反应式业务的处理
        // 从Spring Framework 5.2 M2开端,Spring经过ReactiveTransactionManagerSPI 支撑响应式/反应式业务管理
        if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
                ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
                        if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
                                throw new TransactionUsageException(
                                                "Unsupported annotated transaction on suspending function detected: " + method +
                                                ". Use TransactionalOperator.transactional extensions instead.");
                        }
                        ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
                        if (adapter == null) {
                                throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
                                                method.getReturnType());
                        }
                        return new ReactiveTransactionSupport(adapter);
                });
                return txSupport.invokeWithinTransaction(
                                method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
        }
        // 判别 tm是否是 PlatformTransactionManager 类型,是则强转,不是则抛出反常
        PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
        // 结构办法的唯一标识( 全路径了类名.办法)
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
        // 4. 对不同业务情景的处理
        // 声明式业务的处理
        // 假如txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,履行方针增强
        // 在TransactionManager上,CallbackPreferringPlatformTransactionManager完结PlatformTransactionManager接口,暴露出一个办法用于履行业务处理中的回调
        if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
                // Standard transaction demarcation with getTransaction and commit/rollback calls.
                // 5.假如有必要,创立业务信息。首要因为业务的传达特点,所以这儿并不一定会创立业务
                TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
                Object retVal;
                try {
                        // This is an around advice: Invoke the next interceptor in the chain.
                        // This will normally result in a target object being invoked.
                        // 6. 履行被增强的办法
                        retVal = invocation.proceedWithInvocation();
                }
                catch (Throwable ex) {
                        // target invocation exception
                        // 7. 反常回滚
                        completeTransactionAfterThrowing(txInfo, ex);
                        throw ex;
                }
                finally {
                        // 8. 提交之前铲除业务信息
                        cleanupTransactionInfo(txInfo);
                }
                if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                        // Set rollback-only in case of Vavr failure matching our rollback rules...
                        TransactionStatus status = txInfo.getTransactionStatus();
                        if (status != null && txAttr != null) {
                                retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                        }
                }
                // 9.提交业务
                commitTransactionAfterReturning(txInfo);
                return retVal;
        }
        // 编程式业务(CallbackPreferringPlatformTransactionManager)的处理。这儿的逻辑根本都被封装了
        else {
                final ThrowableHolder throwableHolder = new ThrowableHolder();
                try {
                        // 直接调用execute 办法。因为业务的提交回滚等操作都现已封装好了,所以这儿并没有对业务进行详细的操作。
                        Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
                                // 准备业务信息
                                TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
                                try {
                                        // 履行办法
                                        Object retVal = invocation.proceedWithInvocation();
                                        if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                                                // Set rollback-only in case of Vavr failure matching our rollback rules...
                                                retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                                        }
                                        return retVal;
                                }
                                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.
                                                throwableHolder.throwable = ex;
                                                return null;
                                        }
                                }
                                finally {		
                                        // 铲除业务信息	
                                        cleanupTransactionInfo(txInfo);
                                }
                        });
                        // Check result state: It might indicate a Throwable to rethrow.
                        if (throwableHolder.throwable != null) {
                                throw throwableHolder.throwable;
                        }
                        return result;
                }
                catch (ThrowableHolderException ex) {
                        throw ex.getCause();
                }
                catch (TransactionSystemException ex2) {
                        if (throwableHolder.throwable != null) {
                                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                                ex2.initApplicationException(throwableHolder.throwable);
                        }
                        throw ex2;
                }
                catch (Throwable ex2) {
                        if (throwableHolder.throwable != null) {
                                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                        }
                        throw ex2;
                }
        }
}

从上面的代码中,咱们能够知道Spring支撑声明式业务和编程式业务两种处理。两者的完结本质根本相同。在invoke办法中咱们也能够看到这两种办法的完结,通常咱们运用的都是经过 @Transactional 注解润饰的声明式业务,所以咱们下面首要剖析 声明式业务 的处理进程。

  1. 获取业务特点 TransactionAttributeTransactionAttribute 中包括 传达特点,timeout 等业务特点信息。假如是运用 @Transactional 注解,这个解析进程是在AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method) 中完结。

  2. 加载装备中的 TrancationManager, 业务管理器,是业务完结的根底,咱们这儿获取到的是 DataSourceTransactionManager

  3. 对反应式业务的处理。

  4. 不同业务处理办法运用不同的逻辑。在上面的代码中首要是两种状况,一是声明式业务,这种状况是经过 @Transactional 注解润饰办法来表示开启业务。另一种状况是编程式业务,即能够经过xml办法或者装备类办法来进行完结业务功用,其实TransactionTemplate 的完结便是编程式业务,但经过TransactionTemplate并不会走到这个逻辑,这儿的编程式业务应该独自是经过xml或者装备类办法来装备的。

    • 关于声明式业务的处理和编程式业务的处理,差异首要在两点。一是业务特点上,因为编程式业务是不需求业务特点的,二是 TransactionManager 的不同,CallbackPreferringPlatformTransactionManager 完结了 PlatformTransactionManager 接口,暴露了一个办法用于履行业务处理中的回调。所以这两种办法都能够作为业务处理办法的判别。
  5. 在方针办法履行前获取业务并搜集业务信息。

    • 业务信息与业务特点并不相同,也便是 TransactionInfoTransactionAttribute 并不相同,TransactionInfo 中包括TransactionAttribute 信息,而且处理 TransactionAttribute 之外还有其他事物信息,比如PlatformTransactionManager 以及 TransactionStatus相关信息。
  6. 履行方针办法

  7. 假如出现反常,则进行回滚。这儿需求留意,默许的状况下只有 RuntimeException 反常才会履行回滚。能够经过 @Transactional(rollbackFor = Exception.class) 的办法来指定触发回滚的反常

  8. 提交业务前的业务信息铲除

  9. 提交业务

  10. 若是 编程式业务,则直接履行execute办法即可,这儿就不再解说。

注: PlatformTransactionManagerReactiveTransactionManager 二者都是为了完结业务,PlatformTransactionManager 在内部进行业务履行流程的封装,而且暴露出来一个 execute 办法用于履行业务的详细信息,TransactionTemplate 的声明式业务便是基于此完结的。而 ReactiveTransactionManager 则是比较原始的,需求咱们自己来完结业务的整个逻辑。

上面比较笼统的讲了业务的完结,下面们首要剖析以下三个办法,也是业务的的要害流程:

  • 业务的创立 – createTransactionIfNecessary
  • 业务的回滚 – completeTransactionAfterThrowing
  • 业务的提交 – commitTransactionAfterReturning

参阅文章

Spring5源码注释github地址
Spring源码深度解析(第2版)
spring源码解析
Spring源码深度解析笔记
Spring注解与源码剖析
Spring注解驱动开发B站教程