Spring事务原理?事务在方法间如何传播?为什么会失效?( 三 )


AOP零配置原理使用过SpringBoot的都知道 , 如果需要开启事务注解的支持 , 只需要一个注解就能搞定:@EnableTransactionManagement , 不用再配置xml文件 , 这个又是怎么做到的呢?不多说 , 我们直接来看其源码:
@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement { boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE;}在该注解下使用@Import导入了一个类TransactionManagementConfigurationSelector , 首先该注解的作用就是导入一个类的实例到IOC容器中 , 你可能会说不是在类上加@Component注解就行了么 , 但是有些类它并不在你扫描的路径下 , 而该注解依然可以将其导入进来 , 所以我们主要看TransactionManagementConfigurationSelector类中做了些啥:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector { @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); }}可以看到在selectImports方法中返回了AutoProxyRegistrar和ProxyTransactionManagementConfiguration类 , 返回后会被封装为BeanDefinition对象 , 那这个方法是在哪里调用的呢?这个在之前的文章中也分析过 , ConfigurationClassPostProcessor类中会调用ConfigurationClassParser类的parse方法解析@Configuration、@Import、@ImportSource等注解 , 具体过程这里就不再赘述了 。 我们继续来分别看看AutoProxyRegistrar和ProxyTransactionManagementConfiguration类:
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar { private final Log logger = LogFactory.getLog(getClass()); @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean candidateFound = false;Set annoTypes = importingClassMetadata.getAnnotationTypes();for (String annoType : annoTypes) {AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);if (candidate == null) {continue;}Object mode = candidate.get("mode");Object proxyTargetClass = candidate.get("proxyTargetClass");if (mode != nullif (mode == AdviceMode.PROXY) {//注册事务AOP的入口类InfrastructureAdvisorAutoProxyCreator,实际上这个AOP入口类起不了作用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);if ((Boolean) proxyTargetClass) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);return;}}}} }}public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { /* * 明显是创建事务切面实例 * BeanFactoryTransactionAttributeSourceAdvisor * * */ @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());//设置通知类advisor.setAdvice(transactionInterceptor());if (this.enableTx != null) {advisor.setOrder(this.enableTx.getNumber("order"));}return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource(); } /* * 创建事务advice * 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; }}看到这就很清楚了 , 前者是注册AOP的入口类(这里注册的入口类依然是InfrastructureAdvisorAutoProxyCreator) , 后者则是创建事务AOP的组件的实例到IOC中 , 到这里相信不仅仅是对于事务的零配置 , 而是整个SpringBoot的零配置实现原理都心中有数了 。
总结本篇结合之前所学分析了事务配置解析的原理 , 也带出了SpringBoot零配置实现的原理 。 我们需要在脑海将加载、解析和调用串联起来 , 从微观到宏观整体把握Spring , 才能真正的理解Spring 。