ProxyTransactionManagementConfiguration
它是一个@Configuration
,所以看看它向容器里注入了哪些Bean
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { // 这个Advisor可是事务的核心内容。。。。。也是本文重点分析的对象 @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); advisor.setAdvice(transactionInterceptor()); // 顺序由@EnableTransactionManagement注解的Order属性来指定 默认值为:Ordered.LOWEST_PRECEDENCE if (this.enableTx != null) { advisor.setOrder(this.enableTx.<Integer>getNumber("order")); } return advisor; } // TransactionAttributeSource 这种类特别像 `TargetSource`这种类的设计模式 // 这里直接使用的是AnnotationTransactionAttributeSource 基于注解的事务属性源~~~ @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { return new AnnotationTransactionAttributeSource(); } // 事务拦截器,它是个`MethodInterceptor`,它也是Spring处理事务最为核心的部分 // 请注意:你可以自己定义一个TransactionInterceptor(同名的),来覆盖此Bean(注意是覆盖) // 另外请注意:你自定义的BeanName必须同名,也就是必须名为:transactionInterceptor 否则两个都会注册进容器里面去~~~~~~ @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); // 事务的属性 interceptor.setTransactionAttributeSource(transactionAttributeSource()); // 事务管理器(也就是注解最终需要使用的事务管理器,父类已经处理好了) // 此处注意:我们是可议不用特殊指定的,最终它自己会去容器匹配一个适合的~~~~ if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; } } // 父类(抽象类) 它实现了ImportAware接口 所以拿到@Import所在类的所有注解信息 @Configuration public abstract class AbstractTransactionManagementConfiguration implements ImportAware { @Nullable protected AnnotationAttributes enableTx; /** * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}. */ // 此处:注解的默认的事务处理器(可议通过实现接口TransactionManagementConfigurer来自定义配置) // 因为事务管理器这个东西,一般来说全局一个就行,但是Spring也提供了定制化的能力~~~ @Nullable protected PlatformTransactionManager txManager; @Override public void setImportMetadata(AnnotationMetadata importMetadata) { // 此处:只拿到@EnableTransactionManagement这个注解的就成~~~~~ 作为AnnotationAttributes保存起来 this.enableTx = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false)); // 这个注解是必须的~~~~~~~~~~~~~~~~ if (this.enableTx == null) { throw new IllegalArgumentException("@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName()); } } // 这里和@Async的处理一样,配置文件可以实现这个接口。然后给注解驱动的给一个默认的事务管理器~~~~ // 设计模式都是想通的~~~ @Autowired(required = false) void setConfigurers(Collection<TransactionManagementConfigurer> configurers) { if (CollectionUtils.isEmpty(configurers)) { return; } // 同样的,最多也只允许你去配置一个~~~ if (configurers.size() > 1) { throw new IllegalStateException("Only one TransactionManagementConfigurer may exist"); } TransactionManagementConfigurer configurer = configurers.iterator().next(); this.txManager = configurer.annotationDrivenTransactionManager(); } // 注册一个监听器工厂,用以支持@TransactionalEventListener注解标注的方法,来监听事务相关的事件 // 后面会专门讨论,通过事件监听模式来实现事务的监控~~~~ @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public static TransactionalEventListenerFactory transactionalEventListenerFactory() { return new TransactionalEventListenerFactory(); } }
关于事务相关的基础类打点,建议先参阅:
【小家Spring】Spring事务相关的基础类打点(spring-jdbc和spring-tx两个jar),着重讲解AnnotationTransactionAttributeSource
下面重中之重来了,那就是BeanFactoryTransactionAttributeSourceAdvisor这个增强器
BeanFactoryTransactionAttributeSourceAdvisor
首先看它的父类:AbstractBeanFactoryPointcutAdvisor这个之前在讲述AOP的时候已经大篇幅解释过:
【小家Spring】Spring AOP之Advisor、PointcutAdvisor、IntroductionAdvisor、IntroductionInterceptor(引介增强)
父类是一个和Bean工厂有关的Advisor。
再看自己,它是一个和Bean工厂和事务都有关系的Advisor
从上面的配置类可议看出,它是new出来一个。
使用的Advice为:advisor.setAdvice(transactionInterceptor()),既容器内的事务拦截器~~~~
使用的事务属性源为:advisor.setTransactionAttributeSource(transactionAttributeSource()),既一个new AnnotationTransactionAttributeSource()支持三种事务注解来标注~~~
// @since 2.5.5 // 它是一个AbstractBeanFactoryPointcutAdvisor ,关于这个Advisor 请参阅之前的博文讲解~~~ public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { @Nullable private TransactionAttributeSource transactionAttributeSource; // 这个很重要,就是切面。它决定了哪些类会被切入,从而生成的代理对象~ // 关于:TransactionAttributeSourcePointcut 下面有说~ private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { // 注意此处`getTransactionAttributeSource`就是它的一个抽象方法~~~ @Override @Nullable protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } }; // 可议手动设置一个事务属性源~ public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) { this.transactionAttributeSource = transactionAttributeSource; } // 当然我们可以指定ClassFilter 默认情况下:ClassFilter classFilter = ClassFilter.TRUE; 匹配所有的类的 public void setClassFilter(ClassFilter classFilter) { this.pointcut.setClassFilter(classFilter); } // 此处pointcut就是使用自己的这个pointcut去切入~~~ @Override public Pointcut getPointcut() { return this.pointcut; } }
下面当然要重点看看TransactionAttributeSourcePointcut
,它是怎么切入的
TransactionAttributeSourcePointcut
这个就是事务的匹配Pointcut切面,决定了哪些类需要生成代理对象从而应用事务。
// 首先它的访问权限事default 显示是给内部使用的 // 首先它继承自StaticMethodMatcherPointcut 所以`ClassFilter classFilter = ClassFilter.TRUE;` 匹配所有的类 // 并且isRuntime=false 表示只需要对方法进行静态匹配即可~~~~ abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { // 方法的匹配 静态匹配即可(因为事务无需要动态匹配这么细粒度~~~) @Override public boolean matches(Method method, Class<?> targetClass) { // 实现了如下三个接口的子类,就不需要被代理了 直接放行 // TransactionalProxy它是SpringProxy的子类。 如果是被TransactionProxyFactoryBean生产出来的Bean,就会自动实现此接口,那么就不会被这里再次代理了 // PlatformTransactionManager:spring抽象的事务管理器~~~ // PersistenceExceptionTranslator对RuntimeException转换成DataAccessException的转换接口 if (TransactionalProxy.class.isAssignableFrom(targetClass) || PlatformTransactionManager.class.isAssignableFrom(targetClass) || PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) { return false; } // 重要:拿到事务属性源~~~~~~ // 如果tas == null表示没有配置事务属性源,那是全部匹配的 也就是说所有的方法都匹配~~~~(这个处理还是比较让我诧异的~~~) // 或者 标注了@Transaction这样的注解的方法才会给与匹配~~~ TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); } ... // 由子类提供给我,告诉事务属性源~~~~ 我才好知道哪些方法我需要切嘛~~~ @Nullable protected abstract TransactionAttributeSource getTransactionAttributeSource(); }
关于matches方法的调用时机:只要是容器内的每个Bean,都会经过AbstractAutoProxyCreator#postProcessAfterInitialization从而会调用wrapIfNecessary方法,因此容器内所有的Bean的所有方法在容器启动时候都会执行此matche方法,因此请注意缓存的使用~~~~~
这样结合这篇博文:
【小家Spring】Spring事务相关的基础类打点(spring-jdbc和spring-tx两个jar),着重讲解AnnotationTransactionAttributeSource
就能知道Spring最终会给哪些类生成代理对象,事务可以作用在哪些方法上~~~~
真正的执行事务方法,还是在TransactionInterceptor这个增强器里,这个因为比价比较复杂,所以以一篇单独摘取出来详细讲解~~~请持续关注,就在下一篇哦~