Spring事务的开启原理详解
- 作者: 必有卧槽
- 来源: 51数据库
- 2021-08-27
- 在事务配置类上声明@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事务实现步骤的资料请关注其它相关文章!
