Spring源码之事务(一)— TransactionAutoConfiguration自动配置
总结:
- 在ConfigurationClassParser#parse()中会对deferredImportSelectorHandler进行处理(在处理@ComponentScan 自己所写@Component的类后)
- 处理过程中会调用SpringFactoriesLoader#loadFactoryNames(),去查找所有jar下面META-INF/spring.factories中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值
- ConfigurationClassPostProcessor#processConfigBeanDefinitions()中loadBeanDefinitions对TransactionAutoConfiguration进行BeanDefinition的加载,并注册IOC容器
TransactionAutoConfiguration的BeanDefinition加载解析
调用链:
AbstractApplicationContext#refresh() --> AbstractApplicationContext#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors() --> ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()--> ConfigurationClassPostProcessor#processConfigBeanDefinitions() --> ConfigurationClassPostProcessor#parse() --> ConfigurationClassParser#process() --> ConfigurationClassParser$DeferredImportSelectorGroupingHandler#processGroupImports() --> ConfigurationClassParser#processImports() --> ConfigurationClassParser#processConfigurationClass() --> ConfigurationClassParser#doProcessConfigurationClass()
ConfigurationClassParser#parse() 对延迟ImportSelector进行处理
private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectorHandler.process();
}
调用DeferredImportSelectorGroupingHandler#processGroupImports()
public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
// 给ConfigurationClassParser.groupings赋值
deferredImports.forEach(handler::register);
// DeferredImportSelectorGroupingHandler处理
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
主要handler.processGroupImports()中 grouping.getImports()会查找出所有ConfigurationClassParser$DeferredImportSelectorGroupingHandler中的imports
public void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
exclusionFilter, false);
}
}
}
}
ConfigurationClassParser$DeferredImportSelectorGroupingHandler#getImports()
public Iterable<Group.Entry> getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
会调用AutoConfigurationImportSelector#process()
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
会调用AutoConfigurationImportSelector#getAutoConfigurationEntry()
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
......
return new AutoConfigurationEntry(configurations, exclusions);
}
其中AutoConfigurationImportSelector#getCandidateConfigurations()会查找所有jar下面META-INF/spring.factories,进行loadFactoryNames。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
return configurations;
}
SpringFactoriesLoader#loadFactoryNames()
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
......
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
SpringFactoriesLoader#loadSpringFactories()
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
result = new HashMap<>();
try {
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
String[] factoryImplementationNames =
StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
.add(factoryImplementationName.trim());
}
}
}
}
return result;
}
其中spring-boot-autoconfigure-XX.jar下面META-INF/spring.factories文件中就有:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
附:其中ConfigurationClassParser.groupings赋值,是在ConfigurationClassParser#register()执行的
public void register(DeferredImportSelectorHolder deferredImport) {
Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
(group != null ? group : deferredImport),
key -> new DeferredImportSelectorGrouping(createGroup(group)));
grouping.add(deferredImport);
this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getConfigurationClass());
}
loadBeanDefinitions
this.reader.loadBeanDefinitions(configClasses)进行BeanDefinition的加载,并注册到IOC容器
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
this.reader.loadBeanDefinitions(configClasses);
}
Spring源码之事务(一)— TransactionAutoConfiguration自动配置的更多相关文章
- 源码学习系列之SpringBoot自动配置(篇一)
源码学习系列之SpringBoot自动配置源码学习(篇一) ok,本博客尝试跟一下Springboot的自动配置源码,做一下笔记记录,自动配置是Springboot的一个很关键的特性,也容易被忽略的属 ...
- 源码学习系列之SpringBoot自动配置(篇二)
源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...
- SpringBoot源码学习系列之SpringMVC自动配置
目录 1.ContentNegotiatingViewResolver 2.静态资源 3.自动注册 Converter, GenericConverter, and Formatter beans. ...
- SpringBoot源码学习系列之异常处理自动配置
SpringBoot源码学习系列之异常处理自动配置 1.源码学习 先给个SpringBoot中的异常例子,假如访问一个错误链接,让其返回404页面 在浏览器访问: 而在其它的客户端软件,比如postm ...
- spring源码解析--事务篇(前篇)
对于每一个JAVA程序员,spring应该是再熟悉不过的框架了,它的功能有多强大我就不多说了,既然他有这么强大的功能,是如何实现的呢?这个就需要从他的原理去了解,而最直接了解原理的方式莫过于源码.当然 ...
- spring源码分析---事务篇
上一篇我介绍了spring事务的传播特性和隔离级别,以及事务定义的先关接口和类的关系.我们知晓了用TransactionTemplate(或者直接用底层P的latformTransactionMana ...
- SpringBoot源码学习系列之Locale自动配置
目录 1.spring.messages.cache-duration 2.LocaleResolver 的方法名必须为localeResolver 3.默认LocaleResolver 4.指定默认 ...
- Spring源码阅读笔记03:xml配置读取
前面的文章介绍了IOC的概念,Spring提供的bean容器即是对这一思想的具体实现,在接下来的几篇文章会侧重于探究这一bean容器是如何实现的.在此之前,先用一段话概括一下bean容器的基本工作原理 ...
- Spring源码深度解析之事务
Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...
随机推荐
- 【ST表】SCOI2016 萌萌哒
题目内容 洛谷链接 一个长度为\(n\)的大数,用\(S_1S_2S_3...S_n\)表示,其中\(S_i\)表示数的第\(i\)位,\(S_1\)是数的最高位,告诉你一些限制条件,每个条件表示为四 ...
- linux(centos8):firewalld的运行时日志配置
一,firewalld配置日志的用途: 在生产环境中,firewalld的默认配置是不记录日志 我们通过日志记录下防火墙过滤时拒绝的非法ip, 可以主动把这些有攻击性的ip加入到黑名单, 防患于未然 ...
- Dubbo系列之 (七)网络层那些事(2)
辅助链接 Dubbo系列之 (一)SPI扩展 Dubbo系列之 (二)Registry注册中心-注册(1) Dubbo系列之 (三)Registry注册中心-注册(2) Dubbo系列之 (四)服务订 ...
- .net core autofac asyncinterceptor 异步拦截器开发
autofac使用拦截器实现AOP,是基于Castle.Core的.然而Castle.Core并未提供原生异步支持.所以需要使用帮助类实现,这在autofac官方文档的已知问题中有详细说明: http ...
- LruCache缓存bitmap(二)
Lrucache缓存程序关闭缓存自动清除,所以要在onstart方法中调用,只要不关闭程序缓存就在,除以1024是以kb为单位 public class MainActivity extends Ap ...
- D. Generating Sets 解析(思維)
Codeforce 722 D. Generating Sets 解析(思維) 今天我們來看看CF722D 題目連結 題目 略,請直接看原題 前言 真的是沒想到... @copyright petje ...
- 使用udev高效、动态的管理Linux设备文件
导读: 在Linux环境中,所有的设备都以文件的形式存在,在早期的Linux版本中,/dev目录包含了了所有可能出现的设备文件,很难想象Linux用户如何从大量的设备文件中找到想要的设备文件.举个例子 ...
- K近邻算法:机器学习萌新必学算法
摘要:K近邻(k-NearestNeighbor,K-NN)算法是一个有监督的机器学习算法,也被称为K-NN算法,由Cover和Hart于1968年提出,可以用于解决分类问题和回归问题. 1. 为什么 ...
- Django项目-个人网站之投票模块
Django项目之个人网站 关注公众号"轻松学编程"了解更多. Github地址:https://github.com/liangdongchang/MyWeb.git 感兴趣的可 ...
- FastThreadLocal 是什么鬼?吊打 ThreadLocal 的存在!!
ThreadLocal 大家都知道是线程本地变量,今天栈长再介绍一个神器:FastThreadLocal,从字面上看就是:Fast + ThreadLocal,一个快的 ThreadLocal?这到底 ...