日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

這一次搞懂Spring事務注解的解析方式

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

前言

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

正文

XML標簽的解析

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

配置過事務的應該都不陌生,上面這個配置就是Spring開啟事務注解(@Transactional)支持的配置,而看過我之前文章的應該知道,這個帶前綴的標簽叫自定義標簽,我在之前的文章也分析過自定義標簽的解析過程,所以這里我直接找到對應的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()); }}

可以看到對應的注解解析器就是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執行鏈 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); } }

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

public static void registerAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 將優先級更高的AOP入口類放入到IOC容器中 BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 設置代理生成的方式以及是否緩存代理類到當前線程 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中當前存在的類哪個優先級更高,將更高的放入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; }

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

這一次搞懂Spring事務注解的解析方式

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

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) { // 索引即是優先級,越大優先級越高,IOC中只會存在一個事務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是優先級最低的,基本上不會起作用;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類的作用就是封裝事務注解@Transactional的屬性,這里需要記住其繼承體系以及熟悉該類和其父類的屬性和方法,對后面分析事物切面執行原理有幫助:

這一次搞懂Spring事務注解的解析方式

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

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<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對象,那這個方法是在哪里調用的呢?這個在之前的文章中也分析過,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<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) { //注冊事務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.<Integer>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。

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

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品啊v在线| 免费的成人av| 亚欧洲精品视频在线观看| 99国内精品| 一区免费视频| 男人的天堂久久精品| 亚洲开心激情| 亚洲理论在线| 欧美一区=区三区| 国产精品日本一区二区不卡视频| 国产精品一区高清| 精品一区二区男人吃奶| 水蜜桃久久夜色精品一区| 四虎国产精品免费观看| 在线看片国产福利你懂的| 三上亚洲一区二区| 久久高清免费| 亚洲综合电影一区二区三区| 蜜臀精品久久久久久蜜臀| 日本伊人午夜精品| 国产乱码精品一区二区亚洲| 欧美精品1区| 97精品一区二区| 激情欧美国产欧美| 日韩中文字幕不卡| 午夜天堂精品久久久久| 国产精品v亚洲精品v日韩精品 | 在线一区视频观看| 亚洲国内精品| 久久亚洲一区| 国产精品magnet| 国产综合色区在线观看| 国产一区成人| 欧美精品影院| 色在线中文字幕| 视频一区二区三区入口| 国产欧美一区二区三区精品观看| 色乱码一区二区三区网站| 欧美特黄一区| 欧美久久一区二区三区| 国产精品成人a在线观看| 欧美a级一区| 婷婷成人av| 国产va免费精品观看精品视频| 国模 一区 二区 三区| 日本在线成人| 精品国产免费人成网站| 免费在线视频一区| 美日韩一区二区三区| 久久网站免费观看| 日韩中文字幕无砖| 正在播放日韩精品| 亚洲天堂免费| 日韩伦理一区| 欧美一级网站| 欧美精品黄色| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 美女福利一区二区三区| 久久av在线| 九九99久久精品在免费线bt| 国产午夜久久| bbw在线视频| 日韩有码av| 天堂资源在线亚洲| 国产精品调教| 国产亚洲高清视频| 国产69精品久久| 日韩激情网站| 黄色亚洲在线| av综合电影网站| 国产精品mm| 婷婷成人av| 影院欧美亚洲| 午夜久久中文| 麻豆一区二区三| 日本在线观看不卡视频| 不卡一区2区| 黄色精品视频| 一区二区三区四区日韩| 日本欧美不卡| 亚洲v天堂v手机在线| 久久高清免费| 国产精品二区不卡| 国产精品一区二区中文字幕| 久久亚洲美女| 99久久九九| 激情视频网站在线播放色| 日本不卡一区二区三区| 亚洲欧洲日本mm| av高清不卡| 精品一区视频| 欧美日本不卡| 亚洲美女91| 99精品99| 五月综合激情| 精品国产亚洲一区二区三区在线 | 欧美成a人免费观看久久| 久久不见久久见免费视频7 | 不卡在线一区二区| 九九精品调教| 国产成人调教视频在线观看| 日韩欧美中文字幕在线视频| 激情五月综合网| 人在线成免费视频| 日本欧美国产| 精品一区视频| 精品国产乱码久久久久久樱花| 国产九九精品| 青青青国产精品| 婷婷综合成人| 日韩精品视频网站| 亚洲欧洲av| 免费视频一区二区| 亚洲一区网站| 久久国产精品久久久久久电车| 欧美在线资源| 亚洲国产日韩欧美在线| 欧美在线观看视频一区| 日韩网站中文字幕| 日韩天堂在线| 99精品在线观看| 免费av一区二区三区四区| 亚洲电影在线| 亚洲精品午夜av福利久久蜜桃| 亚洲国产一区二区在线观看 | 影音先锋久久| 国产免费成人| 免费人成网站在线观看欧美高清| 蜜桃一区二区三区| 免播放器亚洲| 日韩专区视频网站| 国产美女精品视频免费播放软件| 国产乱码精品一区二区三区四区 | 久久精品国产99| 久久久久久久欧美精品| 国产精品一区二区精品| 国产伦理久久久久久妇女| 久久精品资源| 日韩电影免费在线观看| 日韩视频网站在线观看| 亚洲福利国产| 在线观看免费一区二区| 综合激情一区| 国产午夜久久av| 国产专区精品| 欧美成人午夜| 免费在线观看不卡| 日本色综合中文字幕| 国产欧美日韩一级| 黄色精品视频| 国产真实久久| 亚洲综合电影一区二区三区| 日韩中文字幕无砖| 国产一区一一区高清不卡| 久久精品一区二区不卡| 欧美成人精品三级网站| 午夜久久免费观看| 视频一区中文字幕精品| 久久香蕉网站| 亚洲性色视频| 日韩精品三区四区| 丰满少妇一区| 国产麻豆久久| 久久成人亚洲| 欧美aa在线视频| 99久久久久国产精品| 亚洲丝袜美腿一区| 国产精品magnet| 99精品小视频| 日韩精品a在线观看91| 成人精品久久| 免费成人av在线播放| 欧美激情一区| 亚洲一级黄色| 欧美三区不卡| 欧美1区2区3区| 久久精品 人人爱| 91欧美在线| 日韩精品一二三区| 精品午夜视频| 免费在线观看不卡| 福利在线免费视频| 亚洲日本在线观看视频| 久久久久久网| 四虎国产精品免费久久| 中文在线资源| 久久最新视频| 精品视频在线你懂得| 午夜亚洲精品| 精品国产午夜肉伦伦影院| 天堂av在线一区| 国产h片在线观看| 美女网站久久| 国产伊人久久| 日韩高清一区二区| 丝袜av一区| 国产毛片精品久久| 欧美天堂亚洲电影院在线观看| 欧美a一区二区| 视频在线观看一区|