欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring事务的开启原理详解

程序员文章站 2023-10-24 12:31:58
在事务配置类上声明@enabletransactionmanagement注解开启事务 在事务配置类上定义数据源 在事务配置类上定义事务管理器 在相关类或者方法上使用@transactional...
  1. 在事务配置类上声明@enabletransactionmanagement注解开启事务
  2. 在事务配置类上定义数据源
  3. 在事务配置类上定义事务管理器
  4. 在相关类或者方法上使用@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 事务