Spring事务的开启原理详解

网友投稿 564 2023-02-04

Spring事务的开启原理详解

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,AdviceMoQeXoXgfYde的默认代理方式是PROXY,jdk代理。所以返回的是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。

我们先分析AutoProxyRegistrar,AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,那在创建bean的时候会调用registerBeanDefinitions方法。registerBeanDefinitions方法的实现:

QeXoXgfY@Override

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

boolean candidateFound = false;

Set 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.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,BeanFactoryTransactionAttQeXoXgfYributeSourceAdvisor、AnnotationTransactionAttributeSource、TransactionInterceptor,而这三个类分别继承Advisor、Advice和Pointcut。即切面所需组件。

总结

@EnableTransactionManagement利用AutoProxyRegistrar启动Spring Aop,使用ProxyTransactionManagementConfiguration配置对应切面部件。

以上就是Spring事务的简单实现步骤的详细内容,更多关于Spring事务实现步骤的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:电脑打开小程序(怎么用电脑打开小程序)
下一篇:详解Spring ApplicationContext加载过程
相关文章

 发表评论

暂时没有评论,来抢沙发吧~