0%

前言

事务的实现原理是 Spring AOP。

用户启用注解驱动的事务功能后,Spring beanFactory 将注册1个事务相关的 AOP。

用户在 bean 的类定义或方法定义中声明事务注解@Transactional,beanFactory 创建该 bean 时,将解析事务注解中的属性作为事务属性。

数据源与事务相关的自动配置类

基于 Web Servlet 与 JDBC 数据源场景

自动配置类

自动配置属性文件

配置文件 org.springframework.boot.autoconfigure.AutoConfiguration.importsspring-autoconfigure-metadata.properties

前言

Spring 中注解驱动的事务使用方法。

  1. 启用注解驱动。
    1. SpringBoot 自动配置声明注解@EnableTransactionManagement
    2. 用户主动声明注解@EnableTransactionManagement
  2. 在期望使用事务的类或方法上声明注解@Transactional
    1. 该注解中支持配置事务相关属性,包括事务传播模式,事务管理器,回滚配置,隔离级别等。

注解-EnableTransactionManagement

启用 Spring 的注解驱动事务管理功能。

前言

<font style="color:rgba(0, 0, 0, 0.9);">SpringApplicationEvent</font>是与 <font style="color:rgba(0, 0, 0, 0.9);background-color:rgba(0, 0, 0, 0.03);">SpringApplication</font> 相关的 <font style="color:rgba(0, 0, 0, 0.9);background-color:rgba(0, 0, 0, 0.03);">ApplicationEvent</font> 的基类。

监听器事件类型

共7个子类(实现类)。

序号名称StepName关联事件类型描述
1应用启动开始spring.boot.application.startingApplicationStartingEvent应用开始启动,进行最基础的初始化
2环境准备完成spring.boot.application.environment-preparedApplicationEnvironmentPreparedEvent配置加载完成,环境变量就绪
3上下文准备完成spring.boot.application.context-preparedApplicationContextInitializedEvent应用上下文创建完成,初始化器已执行
4上下文加载完成spring.boot.application.context-loadedApplicationPreparedEventBean定义加载完成,准备刷新上下文
5应用已启动spring.boot.application.startedApplicationStartedEvent上下文刷新完成,核心容器就绪
6应用准备就绪spring.boot.application.readyApplicationReadyEvent所有运行器执行完毕,应用可正常服务
7应用启动失败spring.boot.application.failedApplicationFailedEvent启动过程中出现异常,启动终止

注意,在响应事件完成之后,才能实现事件名称的效果。

问题标题

AOP 代码抛出 UndeclaredThrowableException 异常

问题描述

AOP 代码抛出 UndeclaredThrowableException 异常。

AOP 内的业务代码抛出了受检异常,该异常未在方法上声明。

问题分析

因使用 lombok 注解 @SneakyThrows,业务方法上未声明受检异常。

方法refresh

源码摘录

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

// org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // Prepare this context for refreshing.
        // 准备工作。包括配置环境信息、配置监听器等。
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        // 获取 beanFactory。默认使用之前步骤创建的`AnnotationConfigServletWebServerApplicationContext`。
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        // 配置`BeanFactory`。包括环境信息,注册一批作为工具的 bean 等。
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            // Bean 工厂进行后处理。注册系统 BeanPostProcessor,Scope 等。
            postProcessBeanFactory(beanFactory);

            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // Invoke factory processors registered as beans in the context.
            // 调用 BeanFactoryPostProcessor 接口方法。
            // 功能是扫描与注册 bean,包括用户自定义配置的 bean 和自动配置类。此时暂未实例化未使用的 bean。
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            // 注册`BeanPostProcessor`。
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // Initialize message source for this context.
            // 初始化`MessageSource`。默认使用之前步骤中自动配置方式创建的`ResourceBundleMessageSource`。
            initMessageSource();

            // Initialize event multicaster for this context.
            // 初始化`ApplicationEventMulticaster`。默认主动创建`SimpleApplicationEventMulticaster`。
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            // 刷新 context。
            // 主要功能是初始化`ThemeSource`和创建`WebServer`。
            onRefresh();

            // Check for listener beans and register them.
            // 注册`ApplicationListener`。
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            // 实例化所有非懒加载的单例 bean。
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            // 完成`refresh`操作,发布`ContextRefreshedEvent`事件。
            // 主要功能包括启动`LifecycleProcessor`(start 方法),
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
            contextRefresh.end();
        }
    }
}

主流程详情

  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
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
--> org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh
    --> org.springframework.context.support.AbstractApplicationContext#refresh
        --> org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#prepareRefresh
            --> org.springframework.context.support.AbstractApplicationContext#prepareRefresh
                --> org.springframework.web.context.support.GenericWebApplicationContext#initPropertySources
                    --> org.springframework.web.context.support.StandardServletEnvironment#initPropertySources
                        --> 初始化`servletContextInitParams``servletConfigInitParams`两类配置信息默认无org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources(org.springframework.core.env.MutablePropertySources, javax.servlet.ServletContext, javax.servlet.ServletConfig)
                --> getEnvironment().validateRequiredProperties();
                    --|> 校验必须的配置信息`org.springframework.core.env.AbstractPropertyResolver#requiredProperties`是否已存在默认无需该类信息校验通过
                    --> org.springframework.core.env.AbstractEnvironment#validateRequiredProperties
                        --> org.springframework.core.env.AbstractPropertyResolver#validateRequiredProperties
                --> `this.applicationListeners`作为`this.earlyApplicationListeners`。
        --> `obtainFreshBeanFactory();`
            --|> 从上下文获取`BeanFactory`,具体是`org.springframework.context.support.GenericApplicationContext#beanFactory`。
            --|> org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
                --> org.springframework.context.support.GenericApplicationContext#refreshBeanFactory
                    --|> `BeanFactory``new AnnotationConfigServletWebServerApplicationContext();`命令的默认构造方法中创建的
                    --|> 具体是在`org.springframework.context.support.GenericApplicationContext#GenericApplicationContext()`中执行`new DefaultListableBeanFactory();`。
                    --|> 补充说明:`AnnotationConfigServletWebServerApplicationContext`的无参数构造方法中创建了`new AnnotatedBeanDefinitionReader``new ClassPathBeanDefinitionScanner`。
        --> `prepareBeanFactory(beanFactory);`
            --|> 配置`BeanFactory`。
            --> 配置`org.springframework.beans.factory.support.AbstractBeanFactory#beanExpressionResolver`,执行`new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())`。
            --> 配置`org.springframework.beans.factory.support.AbstractBeanFactory#propertyEditorRegistrars`,执行`new ResourceEditorRegistrar(this, getEnvironment())`。        
            --> `new ApplicationContextAwareProcessor(this))`,添加系统`BeanPostProcessor`。
            --> 配置若干`ignoreDependencyInterface`。
            --> 注册若干`ResolvableDependency`。
            --> `new ApplicationListenerDetector(this)`,添加系统`BeanPostProcessor`。
            --> `LoadTimeWeaver`相关配置
            --> 注册若干 bean包括`environment`,`systemProperties`,`systemEnvironment`,`applicationStartup`。
        --> `postProcessBeanFactory(beanFactory);`。
            --|> 允许在上下文子类中对 Bean 工厂进行后处理
            --|> org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#postProcessBeanFactory
            --> org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#postProcessBeanFactory
                --> `new WebApplicationContextServletContextAwareProcessor(this)`,添加系统`BeanPostProcessor`。
                --> 配置1个`ignoreDependencyInterface`(`ServletContextAware.class`)。
                --> org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#registerWebApplicationScopes
                    --> 检查当前 BeanFactory 中已存在的 scope 并缓存当前默认为空
                    --> org.springframework.web.context.support.WebApplicationContextUtils#registerWebApplicationScopes(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
                        --> 默认注册2个 scope
                            --|> 名称`request`对应`org.springframework.web.context.request.RequestScope`。
                            --|> 名称`session`对应`org.springframework.web.context.request.SessionScope`。
                        --> 当前`ServletContext`为空如果不为空则会新注册一个 scope `application`。
                        --> 注册若干`ResolvableDependency`,与新注册的 scope 有关
                    --> 如果之前 BeanFactory 中已存在并缓存的 scope将其重新注册以保证其优先级高于先前步骤默认注册的 scope
            --> 如果已注册`basePackages`,则调用`this.scanner.scan`扫描和注册 bean默认无
                --|> 关联提前注册方法`org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#scan`。
            --> 如果已注册`annotatedClasses`,则调用`this.reader.registern`扫描和注册 bean默认无
                --|> 关联提前注册方法`org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#register`。
        --> `invokeBeanFactoryPostProcessors(beanFactory);`。
            --|> org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
            --> org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
                --|> 默认`beanFactoryPostProcessors`有3个其中2个是`BeanDefinitionRegistryPostProcessor`,第3个是`SpringApplication$PropertySourceOrderingBeanFactoryPostProcessor`。
                --> for-each beanFactoryPostProcessors处理`BeanDefinitionRegistryPostProcessor`实现类默认有2个如下
                    --|> SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor
                        --|> 注册 bean `SharedMetadataReaderFactoryBean.class`。
                        --|> 为名为`org.springframework.context.annotation.internalConfigurationAnnotationProcessor` bean 配置`metadataReaderFactory`,
                    --|> ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor
                        --|> 打印已存在的指定警告信息
                --> 第1次`beanFactory`中获取`BeanDefinitionRegistryPostProcessor`实现类缓存到`postProcessorNames`,默认1个
                    --|> `org.springframework.context.annotation.internalConfigurationAnnotationProcessor`
                --> for-each postProcessorNames匹配`PriorityOrdered.class`的实现类进行实例化并缓存到`currentRegistryProcessors`。
                    --> beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)
                    --> 筛选得到 1 ,`internalConfigurationAnnotationProcessor`名称对应的`ConfigurationClassPostProcessor`。
                --> 排序。`org.springframework.context.support.PostProcessorRegistrationDelegate#sortPostProcessors`。
                --> 使用`currentRegistryProcessors`注册 bean。`org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors`
                    --> for-each currentRegistryProcessors调用接口方法`org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry`。
                        --> ConfigurationClassPostProcessor
                            --> org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
                            --|> 该方法的逻辑较为复杂在另外的篇章中介绍
                --> 清空缓存`currentRegistryProcessors`。
                --> 第2次`beanFactory`中获取`BeanDefinitionRegistryPostProcessor`实现类缓存到`postProcessorNames`,默认2个
                    --> 已解析过org.springframework.context.annotation.internalConfigurationAnnotationProcessor
                    --> 此为用户自定义声明的 mybatis 相关的注解`@MapperScan`。tech.gdev.springbasicexplore.App#MapperScannerRegistrar#0
                --> for-each postProcessorNames匹配`Ordered.class`的实现类进行实例化并缓存到`currentRegistryProcessors`。
                    --> 筛选得到 0 
                --> 排序。`org.springframework.context.support.PostProcessorRegistrationDelegate#sortPostProcessors`。
                    --|> 参见前文
                --> 使用`currentRegistryProcessors`注册 bean。`org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors`
                    --|> 具体参见前文
                --> 清空缓存`currentRegistryProcessors`。
                --> while 循环
                    --> 具体逻辑与第12次相同区别在于不再以`PriorityOrdered``Ordered`为条件过滤
                    --> 因用户自定义声明的 mybatis 相关的注解`@MapperScan`,因此可以扫描到新的 bean 定义
                --> invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
                    --|> 使用`registryProcessors`,即特殊的`BeanDefinitionRegistryPostProcessor`的实现类调用接口方法`org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory`。
                    --> SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor 空逻辑跳过
                    --> ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor 空逻辑跳过
                    --> ConfigurationClassPostProcessor 
                        --|> 增强`ConfigurationClasses`,详情参见介绍`ConfigurationClassPostProcessor`的其它篇章
                        --|> 注册`ImportAwareBeanPostProcessor`,`new ImportAwareBeanPostProcessor(beanFactory)`。
                    --> MapperScannerConfigurer 空逻辑跳过                   
                --> invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
                    --|> 使用`regularPostProcessors`,即普通的`BeanFactoryPostProcessor`的实现类调用接口方法`org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory`。
                    --> SpringApplication$PropertySourceOrderingBeanFactoryPostProcessor
                --> `beanFactory`中获取`BeanFactoryPostProcessor`实现类缓存到`postProcessorNames`,默认1个
                    --|> priorityOrderedPostProcessors = {ArrayList@7019}  size = 1
                    --|> 0 = {PropertySourcesPlaceholderConfigurer@7041} 
                    --|> orderedPostProcessorNames = {ArrayList@7021}  size = 2
                    --|> 0 = "emBeanDefinitionRegistrarPostProcessor"
                    --|> 1 = "org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor"
                    --|> nonOrderedPostProcessorNames = {ArrayList@7022}  size = 2
                    --|> 0 = "org.springframework.context.event.internalEventListenerProcessor"
                    --|> 1 = "preserveErrorControllerTargetClassPostProcessor"
                    
        --> 注册`BeanPostProcessor`。org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors
            --> org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)
                --> 根据 bean 类型在 beanFactory 中查找`BeanPostProcessor`。 
                --> 注册1个`BeanPostProcessor`,`new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)`,作用大意是打印日志
                -->  bean 分为3类分别是实现`PriorityOrdered`实现`Ordered`和剩余的普通的普通`BeanPostProcessor`。
                --> 处理实现`PriorityOrdered` bean
                    --> 实例化实现`PriorityOrdered` bean缓存其中实现`MergedBeanDefinitionPostProcessor` bean 到局部变量`internalPostProcessors`。
                    --> 排序
                    -->  beanFactory 中将其注册为 BeanPostProcessor即缓存在实例变量`AbstractBeanFactory#beanPostProcessors`区别于注册 bean
                --> `PriorityOrdered`的处理方式注册其它2类 bean
                --> 重新注册局部变量`internalPostProcessors`中的 bean  BeanPostProcessor即将其优先级提到最高
                --> 注册`ApplicationListenerDetector`。`new ApplicationListenerDetector(applicationContext)`。
                --> 最终的 BeanPostProcessor 实例默认有约20个
        --> 初始化`MessageSource`。
            --|> org.springframework.context.support.AbstractApplicationContext#initMessageSource
            --> 优先根据名称`messageSource` beanFactory 中查找如果可以查找到则直接使用
                --|> 默认可以找到
                --|>  bean 为自动配置。`org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration#messageSource`。
                --|> ResourceBundleMessageSource
            --> 否则主动创建`DelegatingMessageSource`,填充 parent context  MessageSource 属性注册到 beanFactory 。`new DelegatingMessageSource()`。
        --> 初始化`ApplicationEventMulticaster`。
            --|> org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster
            --> 优先根据名称`applicationEventMulticaster` beanFactory 中查找如果可以查找到则直接使用
            --> 否则主动创建`SimpleApplicationEventMulticaster`注册到 beanFactory 。。`new SimpleApplicationEventMulticaster(beanFactory);`。
                --|> 默认找不到主动创建
        --> 刷新 context
            --|> `org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh`
            --> 调用父类的方法初始化`ThemeSource`。`org.springframework.web.context.support.GenericWebApplicationContext#onRefresh`
                --> 初始化`ThemeSource`并填充到实例变量`GenericWebApplicationContext#themeSource`
                    --|> `org.springframework.ui.context.support.UiApplicationContextUtils#initThemeSource`
                    --> 优先根据名称`themeSource` beanFactory 中查找如果可以查找到则直接使用
                    --> 否则如果存在 parent context主动创建`DelegatingThemeSource`委托给 parent context
                    --> 否则创建`ResourceBundleThemeSource`。`new ResourceBundleThemeSource();`
            --> 创建`WebServer`。`org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer`。 
                --> 如果当前不存在 webServer 且不存在 servletContext则创建
                    --|> 默认需要创建
                    --|> 创建并启动 Tomcat
                    --> 待补充
                --> 如果当前已存在 webServer  servletContext 不为空则仅初始化。`getSelfInitializer().onStartup(servletContext);`。 
                    --|> 
                --> 初始化`PropertySource`。
                    --|> org.springframework.web.context.support.GenericWebApplicationContext#initPropertySources
        --> 注册`ApplicationListener`。
            --> `AbstractApplicationContext#applicationListeners`中的监听器注册到`AbstractApplicationContext#applicationEventMulticaster`
                --|> 默认有14个相比``增加了2个分别是`SharedMetadataReaderFactoryBean``ScheduledAnnotationBeanPostProcessor`。
            --> 根据 bean 类型在 beanFactory 中查找`ApplicationListener`,此处仅查询 bean name不会提前实例化对象 bean name 注册到`AbstractApplicationContext#applicationEventMulticaster`
                --|> 默认有8个
                --> 0 = "&org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
                --> 1 = "listenerBean"
                --> 2 = "org.springframework.context.annotation.internalScheduledAnnotationProcessor"
                --> 3 = "mvcResourceUrlProvider"
                --> 4 = "applicationAvailability"
                --> 5 = "startupTimeMetrics"
                --> 6 = "tomcatMetricsBinder"
                --> 7 = "springApplicationAdminRegistrar"
            --> 如果`AbstractApplicationContext#earlyApplicationEvents`中存在事件则使用`AbstractApplicationContext#applicationEventMulticaster`进行发布可能会涉及到提前实例化监听器 bean
                --|> 默认不存在事件无需发布
        --> 实例化所有非懒加载的单例 bean。`finishBeanFactoryInitialization(beanFactory);`。
            --|> org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
            --> 如果 beanFactory 未配置 conversionService 属性则进行配置默认已完成配置
            --> 如果 beanFactory 未配置 EmbeddedValueResolver则进行配置默认已完成配置
            --> `LoadTimeWeaverAware`相关处理
                --> 此处涉及1个`LoadTimeWeaverAware`实现其名称是`&entityManagerFactory`。
            --> 重置 beanFactory `TempClassLoader` null
            --> 标记冻结 beanFactory 中的 bean 定义。`beanFactory.freezeConfiguration()`
            --> 预创建非懒加载的单例 bean
                --|> org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
                --|> 待补充详情
        --> 完成`refresh`操作发布相应事件
            --|> org.springframework.context.support.AbstractApplicationContext#finishRefresh
            --> 清理 context 级别的缓存
            --> 初始化`LifecycleProcessor`。 
                --|> org.springframework.context.support.AbstractApplicationContext#initLifecycleProcessor
                -->  beanFactory 中根据名称`lifecycleProcessor`查找`LifecycleProcessor`。
                    --|> 默认已存在该 bean
                    --|> 自动配置类路径`org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration#defaultLifecycleProcessor`。
                        --> 默认配置属性`DefaultLifecycleProcessor#timeoutPerShutdownPhase`为30s
                        --|> Specify the maximum time allotted in milliseconds for the shutdown of any phase (group of SmartLifecycle beans with the same 'phase' value). The default value is 30000 milliseconds (30 seconds).
                        --|> 指定任何阶段具有相同phase值的 SmartLifecycle bean 关闭的最大允许时间以毫秒为单位)。默认值为 30000 毫秒30 )。
                --> 如果未找到则创建`DefaultLifecycleProcessor`并注册到 beanFactory 。`new DefaultLifecycleProcessor();`
            --> refresh LifecycleProcessor
                --|> org.springframework.context.support.DefaultLifecycleProcessor#onRefresh
                --> 启动 bean。`startBeans(true);`
                    --|> org.springframework.context.support.DefaultLifecycleProcessor#startBeans
                    --> 获取`Lifecycle`类型的 bean
                        --|> org.springframework.context.support.DefaultLifecycleProcessor#getLifecycleBeans
                        --> 根据类型在 beanFactory 中查询`Lifecycle`。
                        --> 默认有3个查询到4个 bean name其中1个是本身this),跳过该 bean
                        --> "springBootLoggingLifecycle" -> {LoggingApplicationListener$Lifecycle@10501} 
                        --> "webServerGracefulShutdown" -> {WebServerGracefulShutdownLifecycle@10502} 
                        --> "webServerStartStop" -> {WebServerStartStopLifecycle@10503} 
                    --> 根据`Phase`将其分组为若干个`LifecycleGroup`。
                    --> 遍历上一步骤的分组启动分组
                        --|> org.springframework.context.support.DefaultLifecycleProcessor.LifecycleGroup#start
                        --> 排序 members in group然后遍历启动
                            --> org.springframework.context.support.DefaultLifecycleProcessor#doStart
                            --|> 先启动依赖对象再启动自己涉及状态判断等
                        --> LoggingApplicationListener 
                            --|> 更新`LoggingApplicationListener.Lifecycle#running` true
                        --> WebServerGracefulShutdownLifecycle 
                            --|> 启动 WebServer
                            --> org.springframework.boot.web.embedded.tomcat.TomcatWebServer#start
                            --> 发布`ServletWebServerInitializedEvent`事件该事件无响应
                        --> WebServerStartStopLifecycle
                            --|> 更新`WebServerGracefulShutdownLifecycle#running` true
            --> 发布`ContextRefreshedEvent`事件

调用 BeanFactoryPostProcessor 接口方法详情

源码摘录

  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
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // WARNING: Although it may appear that the body of this method can be easily
    // refactored to avoid the use of multiple loops and multiple lists, the use
    // of multiple lists and multiple passes over the names of processors is
    // intentional. We must ensure that we honor the contracts for PriorityOrdered
    // and Ordered processors. Specifically, we must NOT cause processors to be
    // instantiated (via getBean() invocations) or registered in the ApplicationContext
    // in the wrong order.
    //
    // Before submitting a pull request (PR) to change this method, please review the
    // list of all declined PRs involving changes to PostProcessorRegistrationDelegate
    // to ensure that your proposal does not result in a breaking change:
    // https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<>();

    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();

        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();
        }

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}

流程详情

 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
27
28
29
30
31
32
33
34
35
// 调用 BeanFactoryPostProcessor 接口方法详情
// org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)

概述
--> 获取当前已注册并分类的`BeanFactoryPostProcessor`,`org.springframework.context.support.AbstractApplicationContext#beanFactoryPostProcessors`变量中缓存的 bean
    --|> 此处区别于已注册到 beanFactory 但是未分类的 bean即可以根据 bean 类型在 beanFactory 中找到但是未缓存在`AbstractApplicationContext#beanFactoryPostProcessors`变量中的 bean
    --|> 此步骤得到的`BeanFactoryPostProcessor`通常均为系统`BeanFactoryPostProcessor`,来源于硬编码或自动配置均为直接`new`方法创建的实例
--> 从上一步骤获取到`BeanFactoryPostProcessor`中过滤出`BeanDefinitionRegistryPostProcessor`,调用这一批 bean 的接口方法`BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry`。
    --|> 此类的`BeanFactoryPostProcessor`优先级最高
    --|> 此步骤允许继续注册 bean definition
    --|> 排序规则为`org.springframework.core.annotation.AnnotationAwareOrderComparator#INSTANCE`。
    --|> 其余非`BeanDefinitionRegistryPostProcessor`的普通`BeanFactoryPostProcessor`缓存到局部变量`regularPostProcessors`在本方法后续逻辑中处理
--> 根据 bean 类型在 beanFactory 中查找实现`PriorityOrdered``BeanDefinitionRegistryPostProcessor`,进行实例化并排序然后调用接口方法`BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry`。
    --|> 此步骤唯一处理`internalConfigurationAnnotationProcessor`名称对应的`ConfigurationClassPostProcessor`,该类是 bean 扫描和注册的核心类将在 beanFactory 中注册大量的 bean
    --|> 实例化的方式是调用`org.springframework.beans.factory.BeanFactory#getBean(java.lang.String, java.lang.Class<T>)`,通常会执行 beanFactory 的完整生命周期
    --|> 这些 bean 通常是以 bean definition 形式而非已创建的实例注册到 beanFactory 将由 beanFactory 进行实例化
    --|> 此步骤是 beanFactory 中的第1次查找
--> 根据 bean 类型在 beanFactory 中查找实现`Ordered``BeanDefinitionRegistryPostProcessor`,进行实例化并排序然后调用接口方法`BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry`。
    --|> 默认未找到新的`BeanDefinitionRegistryPostProcessor`。
    --|> 处理逻辑与`PriorityOrdered``BeanDefinitionRegistryPostProcessor`的处理方式相同
    --|> 此步骤是 beanFactory 中的第2次查找
--> 循环方式查询到 beanFactory 中的所有普通`BeanDefinitionRegistryPostProcessor`。
    --> 在每个循环中根据 bean 类型在 beanFactory 中查找BeanDefinitionRegistryPostProcessor`,进行实例化并排序然后调用接口方法`BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry`。
    --> 如果无新增的`BeanDefinitionRegistryPostProcessor`,则退出循环
    --|> 此步骤是 beanFactory 中的第3次查找可能查找若干次
--> 实现了`BeanDefinitionRegistryPostProcessor``BeanFactoryPostProcessor`调用接口方法`BeanFactoryPostProcessor#postProcessBeanFactory`。
--> 普通的即未实现`BeanDefinitionRegistryPostProcessor``BeanFactoryPostProcessor`调用接口方法`BeanFactoryPostProcessor#postProcessBeanFactory`。
--> 根据 bean 类型在 beanFactory 中查找所有`BeanFactoryPostProcessor`,暂不实例化
--> 实例化实现`PriorityOrdered``BeanFactoryPostProcessor`,排序后调用接口方法`BeanFactoryPostProcessor#postProcessBeanFactory`。
--> 实例化实现`Ordered``BeanFactoryPostProcessor`,排序后调用接口方法`BeanFactoryPostProcessor#postProcessBeanFactory`。
--> 实例化普通的`BeanFactoryPostProcessor`,排序后调用接口方法`BeanFactoryPostProcessor#postProcessBeanFactory`。


每种`BeanDefinitionRegistryPostProcessor`仅支持注册优先级低于本身的`BeanDefinitionRegistryPostProcessor`,否则优先级无法正确发挥作用
实现`PriorityOrdered``BeanDefinitionRegistryPostProcessor`允许注册实现实现`Ordered`的和普通的`BeanDefinitionRegistryPostProcessor`;如果注册同级的实现`PriorityOrdered` bean会被视为实现`Ordered` bean接口`PriorityOrdered`继承自`Ordered`)。
 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
AbstractApplicationContext#registerBeanPostProcessors

过程中各类 BeanPostProcessor 有序排序如下
internalPostProcessors = {ArrayList@5269}  size = 4
 0 = {PersistenceAnnotationBeanPostProcessor@5387} 
 1 = {CommonAnnotationBeanPostProcessor@5301} 
 2 = {AutowiredAnnotationBeanPostProcessor@5286} 
 3 = {ScheduledAnnotationBeanPostProcessor@5913} 
priorityOrderedPostProcessors = {ArrayList@5267}  size = 4
 0 = {ConfigurationPropertiesBindingPostProcessor@5386} 
 1 = {PersistenceAnnotationBeanPostProcessor@5387} 
 2 = {CommonAnnotationBeanPostProcessor@5301} 
 3 = {AutowiredAnnotationBeanPostProcessor@5286} 
orderedPostProcessors = {ArrayList@5383}  size = 5
 0 = {AnnotationAwareAspectJAutoProxyCreator@5454} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
 1 = {AsyncAnnotationBeanPostProcessor@5530} "proxyTargetClass=false; optimize=false; opaque=false; exposeProxy=false; frozen=false"
 2 = {ScheduledAnnotationBeanPostProcessor@5913} 
 3 = {FilteredMethodValidationPostProcessor@5926} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
 4 = {PersistenceExceptionTranslationPostProcessor@5927} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
nonOrderedPostProcessors = {ArrayList@5908}  size = 6
 0 = {WebServerFactoryCustomizerBeanPostProcessor@5930} 
 1 = {ErrorPageRegistrarBeanPostProcessor@5931} 
 2 = {HealthEndpointConfiguration$HealthEndpointGroupsBeanPostProcessor@5932} 
 3 = {MeterRegistryPostProcessor@5933} 
 4 = {MetricsRepositoryMethodInvocationListenerBeanPostProcessor@5934} 
 5 = {ProjectingArgumentResolverRegistrar$ProjectingArgumentResolverBeanPostProcessor@5935} 

完成全部注册后的 BeanPostProcessor 有序排序如下
org.springframework.beans.factory.support.AbstractBeanFactory#beanPostProcessors
0 = {ApplicationContextAwareProcessor@5944} 
1 = {WebApplicationContextServletContextAwareProcessor@5945} 
2 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@5946} 
3 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@5947} 
4 = {ConfigurationPropertiesBindingPostProcessor@5386} 
5 = {AnnotationAwareAspectJAutoProxyCreator@5454} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
6 = {AsyncAnnotationBeanPostProcessor@5530} "proxyTargetClass=false; optimize=false; opaque=false; exposeProxy=false; frozen=false"
7 = {FilteredMethodValidationPostProcessor@5926} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
8 = {PersistenceExceptionTranslationPostProcessor@5927} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
9 = {WebServerFactoryCustomizerBeanPostProcessor@5930} 
10 = {ErrorPageRegistrarBeanPostProcessor@5931} 
11 = {HealthEndpointConfiguration$HealthEndpointGroupsBeanPostProcessor@5932} 
12 = {MeterRegistryPostProcessor@5933} 
13 = {MetricsRepositoryMethodInvocationListenerBeanPostProcessor@5934} 
14 = {ProjectingArgumentResolverRegistrar$ProjectingArgumentResolverBeanPostProcessor@5935} 
15 = {PersistenceAnnotationBeanPostProcessor@5387} 
16 = {CommonAnnotationBeanPostProcessor@5301} 
17 = {AutowiredAnnotationBeanPostProcessor@5286} 
18 = {ScheduledAnnotationBeanPostProcessor@5913} 
19 = {ApplicationListenerDetector@5937} 

END

printBanner

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// org.springframework.boot.SpringApplication#run(java.lang.String...)
--> 打印横幅 Banner。`printBanner(environment)`。
    --|> `org.springframework.boot.SpringApplication#printBanner`
    --> 当前`this.bannerMode`值为`Mode.CONSOLE`。
    --> `new SpringApplicationBannerPrinter`
        --> `new SpringBootBanner()`
    --> 如果`this.bannerMode`值为`Mode.LOG`
        --|> bannerPrinter.print(environment, this.mainApplicationClass, logger);
        --|> 详情参见下文值为`Mode.CONSOLE`的场景
    --> 如果`this.bannerMode`值为`Mode.CONSOLE`
        --|> bannerPrinter.print(environment, this.mainApplicationClass, System.out);
        --> org.springframework.boot.SpringApplicationBannerPrinter#print(org.springframework.core.env.Environment, java.lang.Class<?>, java.io.PrintStream)
            --> 获取`Banner`。`org.springframework.boot.SpringApplicationBannerPrinter#getBanner`
                --> 获取`ImageBanner`,`org.springframework.boot.SpringApplicationBannerPrinter#getImageBanner`
                    --> 查询属性`spring.banner.image.location`,如果存在则加载并返回
                    -->  classpath 查询文件`banner.``SpringApplicationBannerPrinter#IMAGE_EXTENSION`后缀拼接
                    --> 封装为`ImageBanner`返回
                --> 获取`TextBanner`,`org.springframework.boot.SpringApplicationBannerPrinter#getTextBanner`
                    --|> 查询属性`spring.banner.location`,如果存在则加载并返回
                    --|>  classpath 查询文件`banner.txt`
                    --> 封装为`ResourceBanner`返回
                --> 如果前两个步骤未获取到 Banner即不存在用户自定义 Banner则使用默认`DEFAULT_BANNER`(`SpringBootBanner`)。
            --> 打印`Banner`。调用接口方法`org.springframework.boot.Banner#printBanner`。
            --> 返回`new PrintedBanner(banner, sourceClass);`。

createApplicationContext

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// org.springframework.boot.SpringApplication#run(java.lang.String...)
--> 创建`ApplicationContext`。`createApplicationContext();`。
    --|> `org.springframework.boot.SpringApplication#createApplicationContext`。
    --> `this.applicationContextFactory`默认为`ApplicationContextFactory.DEFAULT`(`new DefaultApplicationContextFactory()`)。
    --> 调用接口方法`org.springframework.boot.ApplicationContextFactory#create`。
        --|> 实际调用`org.springframework.boot.DefaultApplicationContextFactory#create`。
        --> 加载合适的自动配置类`ApplicationContextFactory`的实现类
            --|> `getFromSpringFactories(webApplicationType, ApplicationContextFactory::create, AnnotationConfigApplicationContext::new);`
            --|> org.springframework.boot.DefaultApplicationContextFactory#getFromSpringFactories
            --> `SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class`
                --> SpringBoot 自动配置有2个实现
                --> AnnotationConfigReactiveWebServerApplicationContext.Factory
                --> AnnotationConfigServletWebServerApplicationContext.Factory
            --> `AnnotationConfigServletWebServerApplicationContext`满足条件调用其无参数构造方法(`AnnotationConfigApplicationContext::new`)实例化
 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
27
28
29
// AnnotationConfigServletWebServerApplicationContext 实例化详情
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#AnnotationConfigServletWebServerApplicationContext()
--> org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(org.springframework.beans.factory.support.BeanDefinitionRegistry)
    --> org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.core.env.Environment)
        --> org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
            --> 注册组件。`org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)`
                --> 注册 2 个工具类
                    --|> AnnotationAwareOrderComparator.INSTANCE
                    --|> new ContextAnnotationAutowireCandidateResolver()
                --> 注册 6  bean 定义
                    --|> ConfigurationClassPostProcessor.class
                    --|> AutowiredAnnotationBeanPostProcessor.class
                    --|> CommonAnnotationBeanPostProcessor.class
                    --|> PersistenceAnnotationBeanPostProcessor.class
                    --|> EventListenerMethodProcessor.class
                    --|> DefaultEventListenerFactory.class
--> org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner(org.springframework.beans.factory.support.BeanDefinitionRegistry)
    --> `this(registry, true);`
        --|> org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner(org.springframework.beans.factory.support.BeanDefinitionRegistry, boolean)
        --> org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner(org.springframework.beans.factory.support.BeanDefinitionRegistry, boolean, org.springframework.core.env.Environment)
            --> org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner(org.springframework.beans.factory.support.BeanDefinitionRegistry, boolean, org.springframework.core.env.Environment, org.springframework.core.io.ResourceLoader)
                --> 入参`useDefaultFilters`值为 true配置`includeFilters`。
                    --|> org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#registerDefaultFilters
                    --> 默认规则为由注解`Component.class`修饰
                    --> 如果 classpath 存在`javax.annotation.ManagedBean``javax.inject.Named`, 则也作为`includeFilters`条件
                --> 配置 environment 作为属性
                --> 配置 resourceLoader 属性
                    --> 可能使用了 PathMatchingResourcePatternResolver待确认
                    --> `this.componentsIndex`在此处加载通常未使用

prepareContext

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// org.springframework.boot.SpringApplication#run(java.lang.String...)
--> 准备`ConfigurableApplicationContext`。
    --|> `prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);`
    --|> `org.springframework.boot.SpringApplication#prepareContext`
    --> 配置属性`environment`。
    --> 配置属性。`postProcessApplicationContext`
        --|> org.springframework.boot.SpringApplication#postProcessApplicationContext
        --> 如果 SpringApplication `this.beanNameGenerator`存在则注入到 context此时不存在无法注入
        --> 如果 SpringApplication `this.resourceLoader`存在则注入到 context此时不存在无法注入
        -->  environment  conversionService 注入到 context  beanFactory 
    --> 应用`ApplicationContextInitializer`。`applyInitializers`。
        --|> org.springframework.boot.SpringApplication#applyInitializers
        --> 获取 ApplicationContextInitializer。`org.springframework.boot.SpringApplication#getInitializers`
            --|> 默认有7个`SpringApplication`的构造方法中初始化的
            --|> 有序排列如下
            --> DelegatingApplicationContextInitializer 
                --|> 调用委托类的`initialize`方法委托类来源于配置参数`context.initializer.classes`。
                --|> 默认未配置该参数因此无有效逻辑
            --> SharedMetadataReaderFactoryContextInitializer
                --|> 添加`CachingMetadataReaderFactoryPostProcessor`。
            --> ContextIdApplicationContextInitializer
                --|> 注册`ContextId`作为 context  id
                --|>  id 名称来源于配置参数`spring.application.name`,默认名称为`application`。
            --> ConfigurationWarningsApplicationContextInitializer
                --|> 注册`ConfigurationWarningsPostProcessor`。
                --|> 作用大意是检查禁止`@ComponentScan`配置扫描`org.springframework``org`
            --> RSocketPortInfoApplicationContextInitializer
                --|> 添加1个`ApplicationListener`实现类`RSocketPortInfoApplicationContextInitializer.Listener`。
                --|> 作用是将`server.ports`属性配置到 environment 
                --|> 当前未使用 RSocket
            --> ServerPortInfoApplicationContextInitializer
                --|> 添加1个`ApplicationListener`实现类`ServerPortInfoApplicationContextInitializer`,即添加本身
                --|> 配置端口号 port 属性默认属性名称为`local.server.port`,中间`server`来源于`ServerNamespace`。
            --> ConditionEvaluationReportLoggingListener 
                --|> 添加1个`ApplicationListener`实现类`ConditionEvaluationReportListener`。
                --|> 打印部分日志
    --> 发布`ApplicationContextInitializedEvent`事件
        --|> `listeners.contextPrepared(context);`
        --|> 默认无该事件的响应
    --> 关闭`bootstrapContext`。`bootstrapContext.close(context);`。
    --> 

ApplicationStartedEvent

该事件实际无响应。

分支流程 SpringApplication#prepareEnvironment

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// org.springframework.boot.SpringApplication#prepareEnvironment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    listeners.environmentPrepared(bootstrapContext, environment);
    DefaultPropertiesPropertySource.moveToEnd(environment);
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
            "Environment prefix cannot be set via properties.");
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
        environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

流程

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// org.springframework.boot.SpringApplication#prepareEnvironment
// 构建 Environment
--> 创建`Environment`。
    --|> `org.springframework.boot.SpringApplication#getOrCreateEnvironment`
    --> WebApplicationType.SERVLET 类型调用`org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory#createEnvironment`。
        --> new ApplicationServletEnvironment()
        --|> org.springframework.boot.web.servlet.context.ApplicationServletEnvironment
---> 配置`Environment`。
    --|> `org.springframework.boot.SpringApplication#configureEnvironment`
    --> 创建`ApplicationConversionService`并填充到`environment`,即填充到`AbstractEnvironment#propertyResolver`。
        --|> org.springframework.boot.convert.ApplicationConversionService#ApplicationConversionService()
        --|> 默认`ApplicationConversionService`内包含`org.springframework.core.convert.converter.Converter``org.springframework.format.Formatter`,不包含`java.beans.PropertyEditor`,
        --> 配置转换器org.springframework.boot.convert.ApplicationConversionService#configure
            --> org.springframework.core.convert.support.DefaultConversionService#addDefaultConverters
                --|> 注册`*Converter`,包括
                    --> ScalarConverters
                    --> CollectionConverters
                    --> xxxConverters
            --> org.springframework.format.support.DefaultFormattingConversionService#addDefaultFormatters
                --|> 注册`*Formatter`。
            --> org.springframework.boot.convert.ApplicationConversionService#addApplicationFormatters
                --|> 注册 Spring Boot 相关的`*Formatter`。
            --> org.springframework.boot.convert.ApplicationConversionService#addApplicationConverters
                --|> 注册 Spring Boot 相关的`*Converter`。
            --> 后续逻辑会将其填充到 BeanFactory 
                --> org.springframework.boot.SpringApplication#postProcessApplicationContext
                    --> context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
    --> 配置`PropertySource`并填充到`environment`。
    --> 配置`Profile`并填充到`environment`。空逻辑跳过
--> 封装和添加`ConfigurationPropertySourcesPropertySource`。
    --|> `org.springframework.boot.context.properties.source.ConfigurationPropertySources#attach`
    --|> 将当前的`MutablePropertySources`封装为`SpringConfigurationPropertySources`,并再次封装为支持参数解析的`ConfigurationPropertySourcesPropertySource`,名称为`ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties"`,添加到`MutablePropertySources`中并且优先级最高
--> 发布`ApplicationEnvironmentPreparedEvent`。
    --|> `listeners.environmentPrepared(bootstrapContext, environment);`
    --> 生效的`listener`如下
    --|> EnvironmentPostProcessorApplicationListener
        --> 加载`org.springframework.boot.env.EnvironmentPostProcessor`
            --|> `org.springframework.boot.env.EnvironmentPostProcessorApplicationListener#getEnvironmentPostProcessors`。
            --|> `EnvironmentPostProcessorApplicationListener`使用无参构建方法创建
                --> 构造方法为`this(EnvironmentPostProcessorsFactory::fromSpringFactories, new DeferredLogs());`。
            --> 创建`EnvironmentPostProcessorsFactory`,`EnvironmentPostProcessorsFactory::fromSpringFactories`。
                --> 加载`EnvironmentPostProcessor`,默认有7个
                --|> `SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));`
                --> 创建`ReflectionEnvironmentPostProcessorsFactory`。
                --|> 作用是反射创建实例配置参数`DeferredLogFactory`、`ConfigurableBootstrapContext`
            --> 使用该`EnvironmentPostProcessorsFactory`(`ReflectionEnvironmentPostProcessorsFactory`)实例化`EnvironmentPostProcessor`。
                --|> 均使用`DeferredLog`作为`logger`。
        --> 调用接口方法`org.springframework.boot.env.EnvironmentPostProcessor#postProcessEnvironment`。
            --|> 上一步骤默认创建7个分别如下
            --|> RandomValuePropertySourceEnvironmentPostProcessor
                --|> 添加`RandomValuePropertySource``MutablePropertySources`,相当于也同步添加到了`ConfigurationPropertySourcesPropertySource`
            --|> SystemEnvironmentPropertySourceEnvironmentPostProcessor
                --|> An EnvironmentPostProcessor that replaces the systemEnvironment SystemEnvironmentPropertySource with an SystemEnvironmentPropertySourceEnvironmentPostProcessor.OriginAwareSystemEnvironmentPropertySource that can track the SystemEnvironmentOrigin for every system environment property.
                --|> 用1个`SystemEnvironmentPropertySourceEnvironmentPostProcessor.OriginAwareSystemEnvironmentPropertySource`替换`SystemEnvironmentPropertySource`。
            --|> SpringApplicationJsonEnvironmentPostProcessor
                --|> An EnvironmentPostProcessor that parses JSON from spring. application. json or equivalently SPRING_APPLICATION_JSON and adds it as a map property source to the Environment. The new properties are added with higher priority than the system properties.
                --|> 一个 EnvironmentPostProcessor它解析来自 spring.application.json 或等效的 SPRING_APPLICATION_JSON  JSON并将其作为映射属性源添加到环境中新添加的属性优先级高于系统属性
            --|> CloudFoundryVcapEnvironmentPostProcessor
            --|> ConfigDataEnvironmentPostProcessor
                --|> EnvironmentPostProcessor that loads and applies ConfigData to Spring's Environment.
                --|> 用于加载并应用 ConfigData  Spring  Environment 
            --|> DebugAgentEnvironmentPostProcessor
            --|> IntegrationPropertiesEnvironmentPostProcessor
    --|> AnsiOutputApplicationListener配置日志 ANSI 特性
    --|> LoggingApplicationListener
        --|> An ApplicationListener that configures the LoggingSystem. If the environment contains a logging. config property it will be used to bootstrap the logging system, otherwise a default configuration is used.
        --|> 用于配置日志系统如果环境中包含 logging.config 属性它将被用来初始化日志系统否则将使用默认配置
            --> org.springframework.boot.context.logging.LoggingApplicationListener#initialize
    --|> BackgroundPreinitializer
        --|> ApplicationListener to trigger early initialization in a background thread of time-consuming tasks.
        --> 不了解为何将其作为耗时操作org.springframework.boot.autoconfigure.BackgroundPreinitializer#performPreinitialization
    --|> DelegatingApplicationListener默认未起作用
    --|> FileEncodingApplicationListener默认未起作用
--> org.springframework.boot.SpringApplication#bindToSpringApplication
    --|> `spring.main`相关的配置绑定到`SpringApplication`

ConfigDataEnvironmentPostProcessor 详解

 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor#postProcessEnvironment(org.springframework.core.env.ConfigurableEnvironment, org.springframework.boot.SpringApplication)
--> org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor#postProcessEnvironment(org.springframework.core.env.ConfigurableEnvironment, org.springframework.core.io.ResourceLoader, java.util.Collection<java.lang.String>)
    --> new DefaultResourceLoader();
        --|> org.springframework.core.io.DefaultResourceLoader#DefaultResourceLoader()
    --> org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor#getConfigDataEnvironment
        --> new ConfigDataEnvironment(
            --|> org.springframework.boot.context.config.ConfigDataEnvironment#ConfigDataEnvironment
            --|> 默认搜索路径`locations``"optional:classpath:/;optional:classpath:/config/"``"optional:file:./;optional:file:./config/;optional:file:./config/*/"`。通过使用
            --> 构建`Binder`,`org.springframework.boot.context.properties.bind.Binder#get(org.springframework.core.env.Environment)`。
                --> `ConfigurationPropertySources.get(environment);`
                --> new PropertySourcesPlaceholdersResolver(environment)
                    --> new PropertyPlaceholderHelper
                --> `new Binder(sources, placeholdersResolver, null, null, defaultBindHandler);`,`defaultBindHandler`同样为 null
                    --|> org.springframework.boot.context.properties.bind.Binder#Binder(java.lang.Iterable<org.springframework.boot.context.properties.source.ConfigurationPropertySource>, org.springframework.boot.context.properties.bind.PlaceholdersResolver, org.springframework.core.convert.ConversionService, java.util.function.Consumer<org.springframework.beans.PropertyEditorRegistry>, org.springframework.boot.context.properties.bind.BindHandler)
                        --> org.springframework.boot.context.properties.bind.Binder#Binder(java.lang.Iterable<org.springframework.boot.context.properties.source.ConfigurationPropertySource>, org.springframework.boot.context.properties.bind.PlaceholdersResolver, org.springframework.core.convert.ConversionService, java.util.function.Consumer<org.springframework.beans.PropertyEditorRegistry>, org.springframework.boot.context.properties.bind.BindHandler, org.springframework.boot.context.properties.bind.BindConstructorProvider)
                            --> org.springframework.boot.context.properties.bind.Binder#Binder(java.lang.Iterable<org.springframework.boot.context.properties.source.ConfigurationPropertySource>, org.springframework.boot.context.properties.bind.PlaceholdersResolver, org.springframework.core.convert.ConversionService, java.util.function.Consumer<org.springframework.beans.PropertyEditorRegistry>, org.springframework.boot.context.properties.bind.BindHandler, org.springframework.boot.context.properties.bind.BindConstructorProvider)
                                --> org.springframework.boot.context.properties.bind.BindConverter#get
                                    --> 当前`conversionServices``propertyEditorInitializer`均为空因此`BindConverter`获取默认转换器包含`Converter``PropertyEditor`两大类
                                        --|> org.springframework.boot.context.properties.bind.BindConverter#getSharedInstance
                                        --> new BindConverter(null, null);
                                            --|> org.springframework.boot.context.properties.bind.BindConverter#BindConverter
                                            --> new TypeConverterConversionService(propertyEditorInitializer)
                                                --> new TypeConverterConverter(initializer)
                                                    --|> org.springframework.boot.context.properties.bind.BindConverter.TypeConverterConverter#TypeConverterConverter
                                                    --> createTypeConverter()
                                                        --|> org.springframework.boot.context.properties.bind.BindConverter.TypeConverterConverter#createTypeConverter
                                                        --> new SimpleTypeConverter()
                                                            --> new TypeConverterDelegate(this);
                                                                --|> org.springframework.beans.TypeConverterDelegate#TypeConverterDelegate(org.springframework.beans.PropertyEditorRegistrySupport)
                                                            --> registerDefaultEditors()
                                            --> ApplicationConversionService.getSharedInstance()
                                                --|> org.springframework.boot.convert.ApplicationConversionService#getSharedInstance
                                                --> new ApplicationConversionService(null, true);
                                                    --|> org.springframework.boot.convert.ApplicationConversionService#ApplicationConversionService(org.springframework.util.StringValueResolver, boolean)
                                                    --> org.springframework.boot.convert.ApplicationConversionService#configure
                                                        --|> 批量注册`Converter``Formatter`。
                                
                                --> 使用`BindConstructorProvider.DEFAULT`。
                                --> 两种 Binder `ValueObjectBinder``JavaBeanBinder`。
            --> logger `DeferredLogs`。
            --> createConfigDataLocationResolvers(
                --|> org.springframework.boot.context.config.ConfigDataEnvironment#createConfigDataLocationResolvers
                    --> new ConfigDataLocationResolvers(
                        --|> org.springframework.boot.context.config.ConfigDataLocationResolvers
                            --> 获取`ConfigDataLocationResolver.class`实现类,`SpringFactoriesLoader.loadFactoryNames(ConfigDataLocationResolver.class`。
                            --> org.springframework.boot.context.config.ConfigDataLocationResolvers#ConfigDataLocationResolvers(org.springframework.boot.logging.DeferredLogFactory, org.springframework.boot.ConfigurableBootstrapContext, org.springframework.boot.context.properties.bind.Binder, org.springframework.core.io.ResourceLoader, java.util.List<java.lang.String>)
                                --> 填充`DeferredLogFactory.class`等信息
                                --> 实例化`ConfigDataLocationResolver.class`实现类默认2个有序排列为`ConfigTreeConfigDataLocationResolver``StandardConfigDataLocationResolver`。
                                    --> ConfigTreeConfigDataLocationResolver
                                    --> StandardConfigDataLocationResolver
                                        --> SpringFactoriesLoader.loadFactories(PropertySourceLoader.class
                                            --|> 获取并实例化`PropertySourceLoader.class`实现类
                                            --|> 默认支持如下2种
                                            --|> PropertiesPropertySourceLoader 支持查找`properties``xml`。
                                            --|> YamlPropertySourceLoader 支持查找`yml``yaml` 
            --> 入参`this.environmentUpdateListener`为空使用默认空实现`ConfigDataEnvironmentUpdateListener.NONE`,无逻辑
                --|> 该类监听器响应2种事件分别为
                --|> `onPropertySourceAdded`,属性源添加事件
                --|> `onSetProfiles`,profile 设置事件
            --> new ConfigDataLoaders(
                --> SpringFactoriesLoader.loadFactoryNames(ConfigDataLoader.class, classLoader))
                    --|> 获取并实例化`ConfigDataLoader.class`实现类
                        --|> 默认支持如下2种
                        --|> ConfigTreeConfigDataLoader
                        --|> StandardConfigDataLoader
            --> `createContributors(binder);`
                --|> org.springframework.boot.context.config.ConfigDataEnvironment#createContributors(org.springframework.boot.context.properties.bind.Binder)
                --> for-each 遍历 propertySources封装为`ConfigDataEnvironmentContributor`
                    --|> 此处忽略名称为`defaultProperties` propertySource后续封装应当是为了适配优先级
                    --> ConfigDataEnvironmentContributor.ofExisting(propertySource)
                        --|> 类型为`org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind#EXISTING`。
                --> 添加若干个初始`ImportContributor`。
                    --|> 类型为`org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind#INITIAL_IMPORT`。
                    --|> 对应配置参数如下
                    --> spring.config.import
                    --> spring.config.additional-location
                    --> spring.config.location
                        --|> 默认搜索路径如下
                        --> "optional:classpath:/;optional:classpath:/config/"
                        --> "optional:file:./;optional:file:./config/;optional:file:./config/*/"
                --> 如果存在则将名称为`defaultProperties` propertySource 封装为`ConfigDataEnvironmentContributor`。
        --> org.springframework.boot.context.config.ConfigDataEnvironment#processAndApply
            --> `new ConfigDataImporter(`
                --|> Imports ConfigData by resolving and loading locations. resources are tracked to ensure that they are not imported multiple times.
                --|> 通过解析和加载位置来导入配置数据跟踪资源以确保它们不会被多次导入
                --> 使用`DeferredLogs`,`ConfigDataLocationResolvers`,`ConfigDataLoaders`
            --> `bootstrapContext`中注册`org.springframework.boot.context.properties.bind.Binder`为原型 bean
            --> `processInitial(`
            --> 创建`ConfigDataActivationContext`。`createActivationContext(`
            --> 加载与 profile 无关的配置文件。`processWithoutProfiles(`
            --> 再次创建`ConfigDataActivationContext`。`withProfiles(`
            --> 加载制定 profile 的配置文件。`processWithProfiles(`
            --> 应用到 environment 。`applyToEnvironment(`

默认将使用StandardConfigDataLoaderPropertiesPropertySourceLoader加载配置文件。