亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

這一次搞懂Spring事務(wù)注解的解析方式

瀏覽:17日期:2023-08-19 10:11:42

前言

事務(wù)我們都知道是什么,而Spring事務(wù)就是在數(shù)據(jù)庫之上利用AOP提供聲明式事務(wù)和編程式事務(wù)幫助我們簡化開發(fā),解耦業(yè)務(wù)邏輯和系統(tǒng)邏輯。但是Spring事務(wù)原理是怎樣?事務(wù)在方法間是如何傳播的?為什么有時候事務(wù)會失效?接下來幾篇文章將重點分析Spring事務(wù)源碼,讓我們徹底搞懂Spring事務(wù)的原理。

正文

XML標簽的解析

<tx:annotation-driven transaction-manager='transactionManager'/>

配置過事務(wù)的應(yīng)該都不陌生,上面這個配置就是Spring開啟事務(wù)注解(@Transactional)支持的配置,而看過我之前文章的應(yīng)該知道,這個帶前綴的標簽叫自定義標簽,我在之前的文章也分析過自定義標簽的解析過程,所以這里我直接找到對應(yīng)的handler:

public class TxNamespaceHandler extends NamespaceHandlerSupport { static final String TRANSACTION_MANAGER_ATTRIBUTE = 'transaction-manager'; static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = 'transactionManager'; static String getTransactionManagerName(Element element) { return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ? element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME); } @Override public void init() { registerBeanDefinitionParser('advice', new TxAdviceBeanDefinitionParser()); registerBeanDefinitionParser('annotation-driven', new AnnotationDrivenBeanDefinitionParser()); registerBeanDefinitionParser('jta-transaction-manager', new JtaTransactionManagerBeanDefinitionParser()); }}

可以看到對應(yīng)的注解解析器就是AnnotationDrivenBeanDefinitionParser類,在該類中一定會有一個parse方法:

public BeanDefinition parse(Element element, ParserContext parserContext) { registerTransactionalEventListenerFactory(parserContext); String mode = element.getAttribute('mode'); if ('aspectj'.equals(mode)) { // mode='aspectj' registerTransactionAspect(element, parserContext); if (ClassUtils.isPresent('javax.transaction.Transactional', getClass().getClassLoader())) { registerJtaTransactionAspect(element, parserContext); } } else { // mode='proxy' AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext); } return null; }

首先拿到mode屬性的值判斷是使用AspectJ生成代理還是JDK生成代理,這里我們主要看proxy模式,進入configureAutoProxyCreator方法:

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) { // 注冊AOP的入口類 AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME; if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) { Object eleSource = parserContext.extractSource(element); // Create the TransactionAttributeSource definition. // @Transactional注解的屬性封裝 RootBeanDefinition sourceDef = new RootBeanDefinition( 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource'); sourceDef.setSource(eleSource); sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef); // Create the TransactionInterceptor definition. // AOP執(zhí)行鏈 RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class); interceptorDef.setSource(eleSource); interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); // 拿到transaction-manager屬性的值 registerTransactionManager(element, interceptorDef); interceptorDef.getPropertyValues().add('transactionAttributeSource', new RuntimeBeanReference(sourceName)); String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef); // Create the TransactionAttributeSourceAdvisor definition. RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class); advisorDef.setSource(eleSource); advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); advisorDef.getPropertyValues().add('transactionAttributeSource', new RuntimeBeanReference(sourceName)); advisorDef.getPropertyValues().add('adviceBeanName', interceptorName); if (element.hasAttribute('order')) { advisorDef.getPropertyValues().add('order', element.getAttribute('order')); } parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource); compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName)); compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName)); compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName)); parserContext.registerComponent(compositeDef); } }

這里的流程比較長,但邏輯很簡單。首先來看注冊事務(wù)AOP入口類是哪個:

public static void registerAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 將優(yōu)先級更高的AOP入口類放入到IOC容器中 BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 設(shè)置代理生成的方式以及是否緩存代理類到當前線程 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); }

主要看registerAutoProxyCreatorIfNecessary方法:

public static BeanDefinition registerAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, 'BeanDefinitionRegistry must not be null'); // 判斷傳進來的類和ICO中當前存在的類哪個優(yōu)先級更高,將更高的放入IOC中 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) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } //把AOP入口類封裝成beanDefinition對象,要實例化 RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add('order', Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); //注解aop入口類的beanName名稱 AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }

首先判斷容器中是否已經(jīng)存在AOP入口類,如果不存在則直接創(chuàng)建InfrastructureAdvisorAutoProxyCreator的BeanDefinition對象注冊到容器中,這個類也是我上一篇文章分析的AOP入口類AbstractAutoProxyCreator的子類,再來看看其繼承關(guān)系:

這一次搞懂Spring事務(wù)注解的解析方式

你會不會疑惑,這么多子類,到底會使用哪一個呢?回到剛剛的代碼中,可以看到如果已經(jīng)存在一個入口類了,就會通過findPriorityForClass獲取兩個類的優(yōu)先級,最終就會使用優(yōu)先級更大的那個,那么它們的優(yōu)先級順序是怎樣的呢?

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); APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); } private static int findPriorityForClass(@Nullable String className) { // 索引即是優(yōu)先級,越大優(yōu)先級越高,IOC中只會存在一個事務(wù)AOP入口類 for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) { Class<?> clazz = APC_PRIORITY_LIST.get(i); if (clazz.getName().equals(className)) { return i; } } throw new IllegalArgumentException( 'Class name [' + className + '] is not a known auto-proxy creator class'); }

可以看到,InfrastructureAdvisorAutoProxyCreator是優(yōu)先級最低的,基本上不會起作用;AspectJAwareAdvisorAutoProxyCreator是當我們配置了<aop:config>標簽時會注冊,也就是xml配置的AOP的入口類;而AnnotationAwareAspectJAutoProxyCreator是當我們配置了<aop:aspectj-autoproxy>或使用@EnableAspectJAutoProxy注解時注冊,因此大部分情況下都是使用的AnnotationAwareAspectJAutoProxyCreator。

注冊完AOP的入口類后,回到configureAutoProxyCreator方法:

RootBeanDefinition sourceDef = new RootBeanDefinition( 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource');sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName =parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

AnnotationTransactionAttributeSource類的作用就是封裝事務(wù)注解@Transactional的屬性,這里需要記住其繼承體系以及熟悉該類和其父類的屬性和方法,對后面分析事物切面執(zhí)行原理有幫助:

這一次搞懂Spring事務(wù)注解的解析方式

緊接著就是創(chuàng)建了TransactionInterceptor對象,專門的事務(wù)攔截器,并且該類是MethodInterceptor的子類,看到這個應(yīng)該不陌生了,我們知道AOP調(diào)用鏈在執(zhí)行過程中主要就是調(diào)用該類的invoke的方法,因此它是事務(wù)切面執(zhí)行的入口。既然有了Interceptor,那么必不可少的還應(yīng)該有Advisor,而Advisor又是由Advice和Poincut組成的,這樣才能構(gòu)成一個完整的切面,所以該方法后面就是創(chuàng)建這兩個對象。以上就是xml配置AOP注解支持的原理,很簡單,下面再來看看零配置又是如何實現(xiàn)的。

AOP零配置原理

使用過SpringBoot的都知道,如果需要開啟事務(wù)注解的支持,只需要一個注解就能搞定:@EnableTransactionManagement,不用再配置xml文件,這個又是怎么做到的呢?不多說,我們直接來看其源碼:

@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement { boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE;}

在該注解下使用@Import導(dǎo)入了一個類TransactionManagementConfigurationSelector,首先該注解的作用就是導(dǎo)入一個類的實例到IOC容器中,你可能會說不是在類上加@Component注解就行了么,但是有些類它并不在你掃描的路徑下,而該注解依然可以將其導(dǎo)入進來,所以我么主要看TransactionManagementConfigurationSelector類中做了些啥:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { @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對象,那這個方法是在哪里調(diào)用的呢?這個在之前的文章中也分析過,ConfigurationClassPostProcessor類中會調(diào)用ConfigurationClassParser類的parse方法解析@Configuration、@Import、@ImportSource等注解,具體過程這里就不再贅述了。我們繼續(xù)來分別看看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<String> 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 != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) { candidateFound = true; if (mode == AdviceMode.PROXY) { //注冊事務(wù)AOP的入口類InfrastructureAdvisorAutoProxyCreator,實際上這個AOP入口類起不了作用 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); if ((Boolean) proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } }}public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { /* * 明顯是創(chuàng)建事務(wù)切面實例 * BeanFactoryTransactionAttributeSourceAdvisor * * */ @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); advisor.setTransactionAttributeSource(transactionAttributeSource()); //設(shè)置通知類 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(); } /* * 創(chuàng)建事務(wù)advice * TransactionInterceptor * */ @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionInterceptor transactionInterceptor() { TransactionInterceptor interceptor = new TransactionInterceptor(); interceptor.setTransactionAttributeSource(transactionAttributeSource()); //事務(wù)管理器要跟數(shù)據(jù)源掛鉤,所以需要自己定義 if (this.txManager != null) { interceptor.setTransactionManager(this.txManager); } return interceptor; }}

看到這就很清楚了,前者是注冊AOP的入口類(這里注冊的入口類依然是InfrastructureAdvisorAutoProxyCreator),后者則是創(chuàng)建事務(wù)AOP的組件的實例到IOC中,到這里相信不僅僅是對于事務(wù)的零配置,而是整個SpringBoot的零配置實現(xiàn)原理都心中有數(shù)了。

總結(jié)

本篇結(jié)合之前所學(xué)分析了事務(wù)配置解析的原理,也帶出了SpringBoot零配置實現(xiàn)的原理,下一篇就是事務(wù)的執(zhí)行調(diào)用過程。我們需要在腦海將加載、解析和調(diào)用串聯(lián)起來,從微觀到宏觀整體把握Spring,才能真正的理解Spring。

以上這篇這一次搞懂Spring事務(wù)注解的解析方式就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持好吧啦網(wǎng)。

標簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 免费毛片a| 国产美女亚洲精品久久久久久 | 亚洲另类视频 | 韩国美女激情视频一区二区 | 大学生一级毛片免费看真人 | 亚洲一区二区三区四区视频 | 日一区二区 | 国产玖玖在线观看 | 亚洲欧美日韩高清一区二区三区 | 亚洲欧美日韩中文高清ww | 男女激情视频国产免费观看 | 高清欧美一区二区三区 | 欧美久久久久久久一区二区三区 | 欧美成人一区二区三区在线电影 | 羞羞影院免费观看网址在线 | 在线观看的黄色网址 | 免费a黄色 | 呦系列视频一区二区三区 | 91色在线观看国产 | 欧美一级三级在线观看 | 日韩伦理中文字幕 | 国产精品原创永久在线观看 | 成人伦理影院 | 黄色日本视频 | 女性无套免费网站在线看 | 美女69xxxxxxxx | 欧美日韩国产超高清免费看片 | 黄色片免| 久草在线资源福利站 | 精品国产品欧美日产在线 | 北条麻妃一区二区三区 | 国内自拍网红在线综合 | 97精品国产自在现线免费 | 国产精品免费大片 | 上海毛片| 在线免费看黄视频 | 日本一区二区在线不卡 | 不卡黄色 | 天堂影院jav成人天堂免费观看 | 黄片毛片一级片 | 成人淫片|