直入主题
我们想要了解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事务是如何织入的基本就讲述完毕了。