Spring事务的开启原理详解
- 在事务配置类上声明@enabletransactionmanagement注解开启事务
- 在事务配置类上定义数据源
- 在事务配置类上定义事务管理器
- 在相关类或者方法上使用@transactional声明事务
代码如下:
@configuration @enabletransactionmanagement public class rootconfig{ @bean public datasource datasource(){ druiddatasource datasource = new druiddatasource(); datasource.setxxx(); ... return datasource; } @bean public platfromtransactionmanager txmanager(){ return new datasourcetransactionmanager(datasource()); } }
@service public class userservice{ @autowired private userrepository userrepository; @transactional public void adduser(user user){ userrepository.save(user); } }
@enabletransactionmanagement开启事务原理解析
@enabletransactionmanagement源码如下:
@target(elementtype.type) @retention(retentionpolicy.runtime) @documented @import(transactionmanagementconfigurationselector.class) public @interface enabletransactionmanagement { boolean proxytargetclass() default false; advicemode mode() default advicemode.proxy; int order() default ordered.lowest_precedence; }
可以看到,@enabletransactionmanagement接口类主要import了transactionmanagementconfigurationselector来实现其注入,而transactionmanagementconfigurationselector又主要使用selectimport方法来实现其注入,代码如下:
@override public final string[] selectimports(annotationmetadata importingclassmetadata) { class<?> annotype = generictyperesolver.resolvetypeargument(getclass(), advicemodeimportselector.class); annotationattributes attributes = annotationconfigutils.attributesfor(importingclassmetadata, annotype); if (attributes == null) { throw new illegalargumentexception(string.format( "@%s is not present on importing class '%s' as expected", annotype.getsimplename(), importingclassmetadata.getclassname())); } advicemode advicemode = attributes.getenum(this.getadvicemodeattributename()); //根据advicemode返回不同的类型,默认是advicemode.proxy。 string[] imports = selectimports(advicemode); if (imports == null) { throw new illegalargumentexception(string.format("unknown advicemode: '%s'", advicemode)); } return imports; } @override protected string[] selectimports(advicemode advicemode) { switch (advicemode) { case proxy: return new string[] {autoproxyregistrar.class.getname(), proxytransactionmanagementconfiguration.class.getname()}; case aspectj: return new string[] {transactionmanagementconfigutils.transaction_aspect_configuration_class_name}; default: return null; } }
其中主要功能点为根据advicemode选择创建不同的bean,advicemode的默认代理方式是proxy,jdk代理。所以返回的是autoproxyregistrar和proxytransactionmanagementconfiguration。
我们先分析autoproxyregistrar,autoproxyregistrar实现了importbeandefinitionregistrar,那在创建bean的时候会调用registerbeandefinitions方法。registerbeandefinitions方法的实现:
@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; //只有@enabletransactionmanagement注解才会走到这里 if (mode == advicemode.proxy) { aopconfigutils.registerautoproxycreatorifnecessary(registry); if ((boolean) proxytargetclass) { aopconfigutils.forceautoproxycreatortouseclassproxying(registry); return; } } } } //... } public static beandefinition registerautoproxycreatorifnecessary(beandefinitionregistry registry, object source) { return registerorescalateapcasrequired(infrastructureadvisorautoproxycreator.class, registry, source); }
可以看到,它通过注册infrastructureadvisorautoproxycreator来启动spring aop。
接下来再看proxytransactionmanagementconfiguration的作用,代码如下:
@configuration public class proxytransactionmanagementconfiguration extends abstracttransactionmanagementconfiguration { @bean(name = transactionmanagementconfigutils.transaction_advisor_bean_name) @role(beandefinition.role_infrastructure) public beanfactorytransactionattributesourceadvisor transactionadvisor() { beanfactorytransactionattributesourceadvisor advisor = new beanfactorytransactionattributesourceadvisor(); advisor.settransactionattributesource(transactionattributesource()); advisor.setadvice(transactioninterceptor()); advisor.setorder(this.enabletx.<integer>getnumber("order")); return advisor; } @bean @role(beandefinition.role_infrastructure) public transactionattributesource transactionattributesource() { return new annotationtransactionattributesource(); } @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; } }
proxytransactionmanagementconfiguration是一个配置文件,注册了三个bean,beanfactorytransactionattributesourceadvisor、annotationtransactionattributesource、transactioninterceptor,而这三个类分别继承advisor、advice和pointcut。即切面所需组件。
总结
@enabletransactionmanagement利用autoproxyregistrar启动spring aop,使用proxytransactionmanagementconfiguration配置对应切面部件。
以上就是spring事务的简单实现步骤的详细内容,更多关于spring事务实现步骤的资料请关注其它相关文章!
推荐阅读
-
Spring Cloud 覆写远端的配置属性实例详解
-
详解Spring Boot 中实现定时任务的两种方式
-
Spring中事务管理的四种方法(银行转账为例)
-
详解spring cloud整合Swagger2构建RESTful服务的APIs
-
详解spring cloud使用Hystrix实现单个方法的fallback
-
MySQL索引背后的数据结构及算法原理详解
-
使用dubbo+zookeeper+spring boot构建服务的方法详解
-
Spring Boot集成Shiro并利用MongoDB做Session存储的方法详解
-
详解关于Vue2.0路由开启keep-alive时需要注意的地方
-
spring cloud-给Eureka Server加上安全的用户认证详解