Spring事务原理一(如何织入AOP)

2,136 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

直入主题

我们想要了解spring的事务原理,首先从注解EnableTransactionManagement入手:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// ********这是重点********这是重点********这是重点********这是重点********
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
  // 这个就决定了是用JDK代理还是CGLIB代理
  // false就是使用JDK代理,针对接口代理
  // true就是直接针对实现类代理
	boolean proxyTargetClass() default false;

	
	AdviceMode mode() default AdviceMode.PROXY;

	
	int order() default Ordered.LOWEST_PRECEDENCE;

}
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
  // 默认是PROXY,所以直接看ProxyTransactionManagementConfiguration这个类
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		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);
	}

}

ProxyTransactionManagementConfiguration

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
  // 主要关注如何创建BeanFactoryTransactionAttributeSourceAdvisor
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
    // 创建一个BeanFactoryTransactionAttributeSourceAdvisor对象,这样的话,在BeanPostProcessor中就可以被获取到,并且针对匹配到的class和method进行增强
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
    // 把下面创建的TransactionAttributeSource实例设置进去
		advisor.setTransactionAttributeSource(transactionAttributeSource);
    // 把下面创建的TransactionInterceptor实例设置进去
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

  // TransactionAttributeSource创建出来后,是要设置进BeanFactoryTransactionAttributeSourceAdvisor的
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

  //TransactionInterceptor创建出来,也是要设置进BeanFactoryTransactionAttributeSourceAdvisor,所以中点还是在上面
	@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中,最主要的就是pointcut和advice,这两个正好组合成一个Advisor。pointcut表示逻辑切入点,advice表示真正的拦截逻辑。

当前我们所了解的代码中,TransactionInterceptor正好作为一个advice被设置进BeanFactoryTransactionAttributeSourceAdvisor中,那么pointcut是如何被设置进去的呢?

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;
  // pointcut是BeanFactoryTransactionAttributeSourceAdvisor对象被创建的时候就直接默认TransactionAttributeSourcePointcut
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
      // 创建出来的pointcut依赖于设置进来的transactionAttributeSource
			return transactionAttributeSource;
		}
	};

在spring AOP的实现当中,有一个findAdvisorsThatCanApply()方法,作用是从一系列Advisor中筛选出合适的Advisor实例

protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
      // 主要是这个方法
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

AopUtils

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
      // 看这里,主要是通过这里来判断。只要目标class或者任何的method被Transactional注解,就返回true
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
      // ******这是重点***********这是重点***********这是重点***********这是重点*****
      // BeanFactoryTransactionAttributeSourceAdvisor通过getPointcut()方法获取TransactionAttributeSourcePointcut实例
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
  // 在TransactionAttributeSourcePointcut中,getMethodMatcher()方法就是返回this,也就是TransactionAttributeSourcePointcut本身
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
  // TransactionAttributeSourcePointcut不是IntroductionAwareMethodMatcher类型
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
        // 通过matches()方法判断目标类中的每一个方法,TransactionAttributeSourcePointcut调用matches()方法,其实就是判断当前方法有没有被Transactional注解。只要有一个方法被Transactional注解,就直接返回true
				if (introductionAwareMethodMatcher != null ?
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}
		return false;
	}

在上述代码中,主要的目标就是找到pointcut,只要被@Transactional注解的class或method都会被作为pointcut。

到这里的话,spring事务是如何织入的基本就讲述完毕了。