前言
spring boot 的自动化配置其实就是在spring 的基础上做的封装,在我们之前对mvc,aop的自动化配置中可以发现–> 只是在spring 的基础上添加了一些特性,可以认为只是一个spring的应用.那么,关于transaction的配置也同样.

解析
和aop自动配置一样,在/META-INF/spring.factories中配置有关transaction的有2个:

org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration
我们这里只分析 TransactionAutoConfiguration

TransactionAutoConfiguration 声明了如下注解:

@Configuration
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
1
2
3
4
5
6
@Configuration–>配置类
@ConditionalOnClass(PlatformTransactionManager.class)–> 当前类路径下存在PlatformTransactionManager.class 时该配置生效
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class,Neo4jDataAutoConfiguration.class })–> 在JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class,Neo4jDataAutoConfiguration.class 之后才解析该类.
@EnableConfigurationProperties(TransactionProperties.class)–> 可通过以下2个属性来配置:

spring.transaction.defaultTimeout–> 配置事务的默认超时时间
spring.transaction.rollbackOnCommitFailure–> 配置是否在事务提交失败时回滚
在 spring boot 源码解析11-ConfigurationClassPostProcessor类加载解析 中 我们知道了spring boot 解析配置的类的属性,对于当前来说,由于TransactionAutoConfiguration有2个内部类,因此会处理内部类:

TransactionTemplateConfiguration, 其注解如下:

@Configuration
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
1
2
@Configuration –> 配置类
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)–> 当PlatformTransactionManager类型的bean存在并且当存在多个bean时指定为Primary的PlatformTransactionManager存在时,该配置类才进行解析
由于TransactionAutoConfiguration是在DataSourceTransactionManagerAutoConfiguration之后才被解析处理的,而在DataSourceTransactionManagerAutoConfiguration中配置了transactionManager,因此, TransactionTemplateConfiguration 会被处理.

TransactionTemplateConfiguration只有一个被@Bean注解的方法,代码如下:

@Bean
@ConditionalOnMissingBean
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(this.transactionManager);
}
1
2
3
4
5
当beanFactory中不存在TransactionTemplate类型的bean时,注册一个id为transactionTemplate,类型为TransactionTemplate的bean

EnableTransactionManagementConfiguration,注解如下:

@Configuration
@ConditionalOnBean(PlatformTransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
1
2
3
@Configuration –> 配置类
@ConditionalOnBean(PlatformTransactionManager.class) –> 当beanFactory中存在PlatformTransactionManager类型的bean时该配置生效
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)–> 当beanFactory不存在AbstractTransactionManagementConfiguration类型的bean时生效.
由于EnableTransactionManagementConfiguration只有内部类,同样首先解析内部类:

JdkDynamicAutoProxyConfiguration:

@Configuration
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
1
2
3
4
5
@Configuration–> 配置类
@EnableTransactionManagement(proxyTargetClass = false)–>启用TransactionManagement, proxyTargetClass = false,表示是面向接口代理.关于这个注解,我们后面会分析.
@ConditionalOnProperty(prefix = “spring.aop”, name = “proxy-target-class”, havingValue = “false”, matchIfMissing = false)–> 配置有spring.aop.proxy-target-class = false时生效,如果没配置,则不生效
CglibAutoProxyConfiguration,代码如下:

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
1
2
3
4
5
@Configuration–> 配置类
@EnableTransactionManagement(proxyTargetClass = true)–>启用TransactionManagement, proxyTargetClass = true,表示是使用cglib进行代理.关于这个注解,我们后面会分析.
@ConditionalOnProperty(prefix = “spring.aop”, name = “proxy-target-class”, havingValue = “true”, matchIfMissing = true)–> 配置有spring.aop.proxy-target-class = true时生效,如果没配置,则默认生效
因此,在默认情况下,EnableTransactionManagementConfiguration 生效的是JdkDynamicAutoProxyConfiguration.

@EnableTransactionManagement 注解如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
// false--> jdk动态代理,true-->cglib代理,默认使用的是jdk动态代理
boolean proxyTargetClass() default false;
// 表明transactional 切面是如何织入的,默认是代理
AdviceMode mode() default AdviceMode.PROXY;
// aop的优先级
int order() default Ordered.LOWEST_PRECEDENCE;
}
1
2
3
4
5
6
7
8
9
10
11
12
该注解通过@Import(TransactionManagementConfigurationSelector.class)注解导入了TransactionManagementConfigurationSelector,类图如下:

因此会调用TransactionManagementConfigurationSelector#selectImports.代码如下:

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;
}
}
1
2
3
4
5
6
7
8
9
10
如果是AdviceMode.PROXY,返回org.springframework.context.annotation.AutoProxyRegistrar,org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration
如果是AdviceMode.ASPECTJ,返回org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration
否则,返回null
此时,由于传入的是AdviceMode.PROXY,因此执行第1步

接着,将第一步的返回值传入processImports中继续调用.

由于AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,因此会将其实例化后,加入到JdkDynamicAutoProxyConfiguration所对应的ConfigurationClass中的importBeanDefinitionRegistrars
ProxyTransactionManagementConfiguration类既不是ImportSelector的子类也不是ImportBeanDefinitionRegistrar的子类,因此会调用ConfigurationClassParser#processConfigurationClass处理.该类的类图如下:

由于AbstractTransactionManagementConfiguration实现了ImportAware接口.因此会调用其setImportMetadata方法.代码如下:

public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableTx = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
if (this.enableTx == null) {
throw new IllegalArgumentException(
"@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
}
}
1
2
3
4
5
6
7
8
从@EnableTransactionManagement 中获取配置信息,封装为AnnotationAttributes.如果@EnableTransactionManagement没有配置属性的话,就会返回null,此时就会抛出IllegalArgumentException.

同时在AbstractTransactionManagementConfiguration声明了一个被@Autowired(required = false)注解的方法:

@Autowired(required = false)
void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
}
TransactionManagementConfigurer configurer = configurers.iterator().next();
this.txManager = configurer.annotationDrivenTransactionManager();
}
1
2
3
4
5
6
7
8
9
10
11
当获得该bean时,会将beanFactory中所有TransactionManagementConfigurer类型得到bean传递给该函数
如果configurers为空,直接return
如果有多个TransactionManagementConfigurer类型的bean,则抛出IllegalStateException
获得PlatformTransactionManager
注意: TransactionManagementConfigurer在spring 中没有实现,因此正常情况下是不会有TransactionManagementConfigurer类型的bean

同时在AbstractTransactionManagementConfiguration中注册了一个id为org.springframework.transaction.config.internalTransactionalEventListenerFactory,类型为TransactionalEventListenerFactory,角色为内部使用的bean,代码如下:

@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionalEventListenerFactory transactionalEventListenerFactory() {
return new TransactionalEventListenerFactory();
}
1
2
3
4
5
6
ProxyTransactionManagementConfiguration中很简单了,声明了3个bean,分别如下:

id 为org.springframework.transaction.config.internalTransactionAdvisor,类型为BeanFactoryTransactionAttributeSourceAdvisor,角色为内部使用的bean.代码如下:

@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;
}
1
2
3
4
5
6
7
8
9
实例化BeanFactoryTransactionAttributeSourceAdvisor
配置 transactionAttributeSource
配置 Advice–>切面
配置aop优先级–>默认Integer.MAX_VALUE
id为transactionAttributeSource,类型为TransactionAttributeSource,角色为内部使用的bean.代码如下:

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
1
2
3
4
5
id为transactionInterceptor,类型为TransactionInterceptor,角色为内部使用的bean.代码如下:

@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;
}
1
2
3
4
5
6
7
8
9
10
视线回到TransactionAutoConfiguration,内部类处理完之后,由于TransactionAutoConfiguration声明了@EnableConfigurationProperties(TransactionProperties.class) 注解,而@EnableConfigurationProperties注解通过@Import(EnableConfigurationPropertiesImportSelector.class)引入了EnableConfigurationPropertiesImportSelector.

因此,接下来会调用ConfigurationClassParser#processImports

由于EnableConfigurationPropertiesImportSelector是ImportSelector的实现,调用其selectImports方法返回的是ConfigurationPropertiesBeanRegistrar,ConfigurationPropertiesBindingPostProcessorRegistrar.

由于ConfigurationPropertiesBeanRegistrar, ConfigurationPropertiesBindingPostProcessorRegistrar是ImportBeanDefinitionRegistrar的实现,添加到TransactionAutoConfiguration对应的importBeanDefinitionRegistrars中.

接着,处理TransactionAutoConfiguration中被@bean注解的方法—> 只有一个,代码如下:

@Bean
@ConditionalOnMissingBean
public TransactionManagerCustomizers platformTransactionManagerCustomizers(
ObjectProvider<List<PlatformTransactionManagerCustomizer<?>>> customizers) {
return new TransactionManagerCustomizers(customizers.getIfAvailable());
}
1
2
3
4
5
6
TransactionAutoConfiguration 配置类解析完之后,会调用ConfigurationClassBeanDefinitionReader#loadBeanDefinitions.会依次处理TransactionAutoConfiguration配置类中生成的ConfigurationClass

ProxyTransactionManagementConfiguration 对应的ConfigurationClass,由于是被JdkDynamicAutoProxyConfiguration导入的,因此会调用ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass方法,代码如下:

private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
AnnotationMetadata metadata = configClass.getMetadata();
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
configBeanDef.setScope(scopeMetadata.getScopeName());
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
configClass.setBeanName(configBeanName);

if (logger.isDebugEnabled()) {
logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
向BeanDefinitionRegistry进行注册.

同时,由于在ProxyTransactionManagementConfiguration中定义了4个@bean方法,因此会依次调用loadBeanDefinitionsForBeanMethod进行注册.

JdkDynamicAutoProxyConfiguration 是被EnableTransactionManagementConfiguration导入,因此同样会调用ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass方法,进行注册.

由于在JdkDynamicAutoProxyConfiguration中importBeanDefinitionRegistrars 配置有AutoProxyRegistrar,因此会调用AutoProxyRegistrar#registerBeanDefinitions.代码如下:

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) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound) {
String name = getClass().getSimpleName();
// log
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
获得importingClassMetadata中的注解类型
依次遍历,如果遍历到@EnableTransactionManagement 注解

如果@EnableTransactionManagement 配置的mode 为PROXY,则注册类型为InfrastructureAdvisorAutoProxyCreator,id为org.springframework.aop.config.internalAutoProxyCreator的bean
如果@EnableTransactionManagement 配置的proxyTargetClass为true,则向beanFactory中id为org.springframework.aop.config.internalAutoProxyCreator的bean添加proxyTargetClass的属性,值为true
如果最终没有找到@EnableTransactionManagement,则打印日志

EnableTransactionManagementConfiguration 是被TransactionAutoConfiguration 导入.因此会调用ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass方法进行注册

TransactionTemplateConfiguration 是被TransactionTemplateConfiguration导入的, 因此会调用ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass方法进行注册.同时由于声明了一个被@bean注解的方法,因此会调用loadBeanDefinitionsForBeanMethod进行注册
TransactionAutoConfiguration 是被启动类导入,因此会调用ConfigurationClassBeanDefinitionReader#registerBeanDefinitionForImportedConfigurationClass方法进行注册.

同时由于有一个被@bean注解的方法,因此会调用loadBeanDefinitionsForBeanMethod进行注册
最后,由于通过@EnableConfigurationProperties间接导入了2个BeanDefinitionsFromRegistrar.依次会依次调用其registerBeanDefinitions方法.

ConfigurationPropertiesBeanRegistrar–> 会向BeanDefinitionRegistry注册一个id为spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties,类型为TransactionProperties的bean
ConfigurationPropertiesBindingPostProcessorRegistrar–>
如果BeanDefinitionRegistry中不存id为org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor的bean,则:

注册id为org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor,类型为ConfigurationBeanFactoryMetaData的bean
注册id为org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.store,类型为ConfigurationBeanFactoryMetaData的bean
注意:关于解析配置类的流程在spring boot 源码解析11-ConfigurationClassPostProcessor类加载解析中详细解析

解析流程图如下:

加载流程就比较简单了,这里就不画了
---------------------
版权声明:本文为CSDN博主「一个努力的码农」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_26000415/article/details/79021958

Springboot Actuator之十一:actuator transaction的更多相关文章

  1. Springboot Actuator之八:actuator的执行原理

    本文接着<Springboot Actuator之七:actuator 中原生endpoint源码解析1>,前面主要分析了原生endpoint的作用. 现在着重了解actuator的执行原 ...

  2. springboot(十九)使用actuator监控应用【转】【补】

    springboot(十九)使用actuator监控应用 微服务的特点决定了功能模块的部署是分布式的,大部分功能模块都是运行在不同的机器上,彼此通过服务调用进行交互,前后台的业务流会经过很多个微服务的 ...

  3. Springboot Actuator之十一:actuator PublicMetrics

    前言接下来的几篇文章我们来分析一下spring-boot-actuator 中在org.springframework.boot.actuate.metrics中的代码,如图: 这里的代码不仅多,而且 ...

  4. SpringBoot 监控管理模块actuator没有权限的问题

    SpringBoot 1.5.9 版本加入actuator依赖后, 访问/beans 等敏感的信息时候报错,如下 Tue Mar 07 21:18:57 GMT+08:00 2017 There wa ...

  5. Springboot监控之一:SpringBoot四大神器之Actuator之3-springBoot的监控和管理--指标说明

    Spring Boot包含很多其他的特性,它们可以帮你监控和管理发布到生产环境的应用.你可以选择使用HTTP端点,JMX或远程shell(SSH或Telnet)来管理和监控应用.审计(Auditing ...

  6. SpringBoot整合Swagger和Actuator

    前言 本篇文章主要介绍的是SpringBoot整合Swagger(API文档生成框架)和SpringBoot整合Actuator(项目监控)使用教程. SpringBoot整合Swagger 说明:如 ...

  7. SpringBoot要点之使用Actuator监控

    Actuator是Springboot提供的用来对应用系统进行自省和监控的功能模块,借助于Actuator开发者可以很方便地对应用系统某些监控指标进行查看.统计等. 在pom文件中加入spring-b ...

  8. Spring Boot]SpringBoot四大神器之Actuator

    论文转载自博客: https://blog.csdn.net/Dreamhai/article/details/81077903 https://bigjar.github.io/2018/08/19 ...

  9. SpringBoot四大神器之Actuator

    介绍 Spring Boot有四大神器,分别是auto-configuration.starters.cli.actuator,本文主要讲actuator.actuator是spring boot提供 ...

随机推荐

  1. 记录下vue keep-alive IOS下无法保存滚动scroll位置的问题

    最近 做的项目,遇到了一点小麻烦,就是我一个页面A页面是加载 列表数据 ,B页面是展示详细信息的.A进去B时,缓存A页面. 效果 做出来 后,缓存是缓存数据 了,但是当我A页面的列表数据 好多,要滚动 ...

  2. SpringBoot学习笔记:http接口请求

    controller package com.example.demo.controller; import java.util.HashMap; import java.util.Map; impo ...

  3. .net web api 权限验证

    做一个登录权限验证. 开始吧. using System; using System.Collections.Generic; using System.Drawing; using System.D ...

  4. MyDAL - .OpenDebug() 与 Visual Studio 输出窗口 使用

    索引: 目录索引 SQL Debug 信息说明 一. 对 XConnection 对象 未开启 OpenDebug, 在 VS  状态下,将默认在 VS 窗口 打印出 参数化的 SQL 执行语句: 新 ...

  5. frameset frame 页面空白

    <html style="background:#213039;"> <head> <title>网站后台管理中心</title> ...

  6. AMD SATA Download (解决win10 磁盘占用100%问题)

    需要下载的AMD SATA 驱动: 下载AMD SATA https://github.com/StoneIsDeveloper/UsefulTools/blob/master/AMD%20SATA/ ...

  7. python 数据库小测试

    1.整理博客 2.详细解释下列mysql执行语句的每个参数与参数值的含义 ​ mysql -hlocalhost -P3306 -uroot -proot # mysql (连接数据库) # hloc ...

  8. 02-linux-换源-ui方式

    换软件源 使用清华的软件源. Ubuntu 的 ui 界面操作^换源 System setting -> Software & update -> Download from -& ...

  9. HBaseAPI

    环境准备 新建项目后在pom.xml中添加依赖: <dependency> <groupId>org.apache.hbase</groupId> <arti ...

  10. eclipse export runnable jar(导出可执行jar包) runnable jar可以执行的

    如果要导出可运行的JAR文件,需要选择Runnable Jar File. 1. 选择要到处JAR文件的工程,右键选择“Export”: 2. 选择“Java-->Runnable JAR fi ...