SpringBoot版本:2.1.1 ==》啓動流程分析彙總
接上篇Spring Boot 2.1.1(十三)啓動流程分析之準備應用上下文
目錄
5、調用已註冊的BeanFactoryPostProcessors Bean
先調用BeanDefinitionRegistryPostProcessors
8、註冊SimpleApplicationEventMulticaster
11、完成beanFactory初始化,初始化所有剩餘的單例bean
public ConfigurableApplicationContext run(String... args) {
....
try {
//本篇內容從本行開始記錄
refreshContext(context);
//本篇內容記錄到這,後續更新
....
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
}
流程分析
感覺這篇內容會有很多呀!懟它!來看源碼。
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
最終調用父類AbstractApplicationContext的refresh()方法。
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();
}
catch (RuntimeException ex) {
stopAndReleaseWebServer();
throw ex;
}
}
可以看到refresh中的步驟都是單個單個的方法,很方便看,下面一個一個方法講。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 準備刷新
prepareRefresh();
// 通知子類刷新內部bean工廠
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 準備bean工廠以便在此上下文中使用
prepareBeanFactory(beanFactory);
try {
// 允許上下文子類中對bean工廠進行後處理
postProcessBeanFactory(beanFactory);
// 在bean創建之前調用BeanFactoryPostProcessors後置處理方法
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 註冊DelegatingMessageSource
initMessageSource();
// 註冊multicaster
initApplicationEventMulticaster();
// 創建內置的Servlet容器
onRefresh();
// 註冊Listener
registerListeners();
// 完成BeanFactory初始化,初始化剩餘單例bean
finishBeanFactoryInitialization(beanFactory);
// 發佈對應事件
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();
}
}
}
開始之前先把AnnotationConfigServletWebServerApplicationContext類圖放這:
1、準備刷新
先調用子類重寫的方法,再調用父類方法。還記得前面講過在創建AnnotationConfigServletWebServerApplicationContext的時候構造方法中實例化了一個ClassPathBeanDefinitionScanner。
@Override
protected void prepareRefresh() {
this.scanner.clearCache();
super.prepareRefresh();
}
子類prepareRefresh()方法
在其父類ClassPathScanningCandidateComponentProvider中有一個MetadataReaderFactory(接口)工廠對象,判斷該對象是否是CachingMetadataReaderFactory這個特定類或者是它的子類的一個實例,返回Boolean值,是就是true,則清除緩存。該類中有個Map,用來緩存每個Spring資源句柄(即每個“.class”文件)的MetadataReader實例。
緩存Map如果是LocalResourceCache(可以看到該類繼承了LinkedHashMap),執行的就是LinkedHashMap的clear()方法了;
else如果緩存不爲空,就是重新new一個LocalResourceCache。
父類prepareRefresh()方法
protected void prepareRefresh() {
//系統啓動時間
this.startupDate = System.currentTimeMillis();
//是否關閉標識,false
this.closed.set(false);
//是否活躍標識,true
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 調用子類GenericWebApplicationContext重寫後的方法替換servlet相關屬性源
initPropertySources();
// 這裏是驗證由ConfigurablePropertyResolver#setRequiredProperties()方法指定的屬性,解析爲非空值,如果沒有設置的話這個方法就不會執行什麼操作。
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
看下最後這個方法,initServlet屬性源,方法註釋是這麼說的將基於Servlet的StubPropertySource替換爲使用給定servletContext和servletConfig對象填充的實例。此方法可以被調用任意次數,但將用相應的實際屬性源替換爲StubPropertySource一次且僅一次。
看下if判斷裏的條件,servletContext不爲空,source中存在指定name的的屬性源,且該屬性源要是StubPropertySource的類型或者是其子類。也就是當第一次調用以後,該屬性源就被替換成了ServletContextPropertySource和ServletConfigPropertySource,所以之後的調用最後一個判斷條件就不會成立了。
public static void initServletPropertySources(MutablePropertySources sources,
@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
Assert.notNull(sources, "'propertySources' must not be null");
//servletContextInitParams
String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;
if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletContextPropertySource(name, servletContext));
}
//servletConfigInitParams
name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;
if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
}
}
看validateRequiredProperties()方法前,先看下Environment的類圖。這裏是驗證由ConfigurablePropertyResolver#setRequiredProperties()方法指定的屬性,解析爲非空值,如果沒有設置的話這個方法就不會執行什麼操作,所以這裏就略過了。
方法最後new了一個LinkedHashSet,收集早期事件,如果multicaster 有用就會廣播事件。
prepareRefresh()就執行完了。
2、通知子類刷新內部bean工廠
可以看到refreshBeanFactory()方法上的註釋說的,什麼都不做:我們擁有一個內部beanfactory,並依靠調用方通過我們的公共方法(或beanfactory)註冊bean。
前面介紹GenericApplicationContext說了與每次刷新創建新的內部beanfactory實例的其他applicationContext實現不同,此上下文的內部beanfactory從一開始就可用,以便能夠在其上註冊bean定義。只能調用一次refresh()。
所以在該方法內只設置了SerializationId,該id是在準備應用上下文時調用ContextIdApplicationContextInitializer時設置的id,在setSerializationId方法中,使用id做key,new了一個弱引用對象爲value,添加到了serializableFactories中,DefaultListableBeanFactory爲被弱引用對象;如果需要,可以通過id得到引用對象,在通過get()方法得到DefaultListableBeanFactory對象。
3、準備bean工廠
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//通知內部bean工廠使用上下文的類加載器
beanFactory.setBeanClassLoader(getClassLoader());
//爲bean定義值中的表達式指定解析策略,即解析el表達式,默認"#{"開頭,"}"結尾
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//在這裏new了一個資源編輯註冊器ResourceEditorRegistrar,該類實現了PropertyEditorRegistrar接口
//作用是使用以下資源編輯器去填充給的的註冊表:ResourceEditor、InputStreamEditor、InputSourceEditor、FileEditor、Urleditor、UriEditor、ClassEditor、ClassArrayEditor。
//如果給的註冊表是PropertyEditorRegistrySupport類型,編輯器交由該類管理
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 向BeanPostProcessor的List中添加一個ApplicationContextAwareProcessor,參數是上下文
//該類作用是將上下文傳遞給實現environmentaware、embeddedValueResolveraware、resourceLoaderware、applicationEventPublisheraware、messageSourceAware或applicationContextaware接口的bean。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//自動裝配忽略給定的類型,添加到忽略的集合中
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//根據第二個參數註冊一個特殊的依賴類型
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 該BeanPostProcessor檢測那些實現了ApplicationListener接口的bean,在它們創建時初始化之後,將它們添加到應用上下文的事件多播器上
//並在這些ApplicationListener bean銷燬之前,將它們從應用上下文的事件多播器上移除。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
//註冊默認environment bean,如果beanfactory不存在environment
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
//systemProperties 同上
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
//systemEnvironment 同上
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
4、允許上下文子類對bean工廠進行後置處理
basePackages和annotatedClasses都爲空。跳過
//AnnotationConfigEmbeddedWebApplicationContext.java
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.postProcessBeanFactory(beanFactory);
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
註冊了一個WebApplicationContextServletContextAwareProcessor。並將ServletContextAware添加到忽略的集合中。再註冊web相關作用域bean。
//ServletWebServerApplicationContext.java
/**
* 註冊 ServletContextAwareProcessor.
* @see ServletContextAwareProcessor
*/
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(
new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
registerWebApplicationScopes();
}
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
registerWebApplicationScopes(beanFactory, null);
}
/**
* Register web-specific scopes ("request", "session", "globalSession", "application")
* with the given BeanFactory, as used by the WebApplicationContext.
* @param beanFactory the BeanFactory to configure
* @param sc the ServletContext that we're running within
*/
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,@Nullable ServletContext sc) {
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
if (sc != null) {
ServletContextScope appScope = new ServletContextScope(sc);
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
// Register as ServletContext attribute, for ContextCleanupListener to detect it.
sc.setAttribute(ServletContextScope.class.getName(), appScope);
}
//註冊ServletRequest的工廠bean
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
//註冊ServletResponse的工廠bean
beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
//註冊HttpSession的工廠bean
beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
//註冊WebRequest的工廠bean
beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
if (jsfPresent) {
FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
}
}
5、調用已註冊的BeanFactoryPostProcessors Bean
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//這裏是委託給了PostProcessorRegistrationDelegate去執行
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
在所有常規bean初始化之前委託PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()去調用BeanFactoryPostProcessors,根據實現BeanDefinitionRegistryPostProcessors ,PriorityOrdered,Ordered接口和其他進行排序,如果有BeanDefinitionRegistryPostProcessors的話,將先調用BeanDefinitionRegistryPostProcessors。這裏最開始得到的BeanFactoryPostProcessor有如下三個。
先調用BeanDefinitionRegistryPostProcessors
這是在準備上下文調用initializers的時候添加的三個後置處理類,其中這兩個類實現了BeanDefinitionRegistryPostProcessors,將會先執行:
- CachingMetadataReaderFactoryPostProcessor
- ConfigurationWarningsPostProcessor
PropertySourceOrderingPostProcessor實現BeanFactoryPostProcessor接口,暫時放到List中。再接下來
首先,調用實現PriorityOrdered的BeanDefinitionRegistryPostProcessors。
在創建上下文的時候是註冊一個ConfigurationClassPostProcessor,該類實現了PriorityOrdered
第二步:調用實現Ordered的BeanDefinitionRegistryPostProcessors。
最後,調用所有其他BeanDefinitionRegistryPostProcessors。
再調用BeanFactoryPostProcessor
調用完BeanDefinitionRegistryPostProcessors,就開始調用BeanFactoryPostProcessor,同樣會根據PriorityOrdered、Ordered進行排序進行先後調用。
首先,調用實現PriorityOrdered的BeanFactoryPostProcessor。
PropertySourcesPlaceholderConfigurer
接下來,調用實現Ordered的BeanFactoryPostProcessor。
最後,調用所有其他BeanFactoryPostProcessor。
最後,清除緩存的合併bean定義,因爲後處理器可能修改了原始元數據,例如替換值中的佔位符…
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
//防止重複調用
Set<String> processedBeans = new HashSet<>();
//判斷beanFactory是否爲BeanDefinitionRegistry對像或是其子類對象
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//用來存放BeanFactoryPostProcessor類型的實例對象
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//用來存放BeanDefinitionRegistryPostProcessor類型的實例對象
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//循環最初得到的BeanFactoryPostProcessor List,優先執行postProcessBeanDefinitionRegistry()方法
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//判斷postProcessor 是否爲BeanDefinitionRegistry對像或是其子類對線
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
//是就轉型,調用postProcessBeanDefinitionRegistry()方法
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
//添加到對應List中
registryProcessors.add(registryProcessor);
}
else {
//如果不是BeanDefinitionRegistry對像或是其子類對象,添加到regularPostProcessors中
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.
//存放當前調用的BeanDefinitionRegistryPostProcessor對象
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先,調用實現PriorityOrdered的BeanDefinitionRegistryPostProcessors
//根據類型得到beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//遍歷beanName
for (String ppName : postProcessorNames) {
//判斷是否實現了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//是則添加到currentRegistryProcessors中
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
//將currentRegistryProcessors中的實例對象添加到registryProcessors中
registryProcessors.addAll(currentRegistryProcessors);
//循環調用postProcessBeanDefinitionRegistry()方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//清空currentRegistryProcessors
currentRegistryProcessors.clear();
// 調用實現Ordered接口的BeanDefinitionRegistryPostProcessors。流程跟上面一樣了
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);
currentRegistryProcessors.clear();
// 最後調用所有其他BeanDefinitionRegistryPostProcessors。
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);
currentRegistryProcessors.clear();
}
// 現在, 調用BeanDefinitionRegistryPostProcessors的postProcessBeanFactory()方法
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<>();
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<>();
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、首先從BeanFactory得到List<BeanFactoryPostProcessor>集合。
2、判斷是否屬於BeanDefinitionRegistryPostProcessors,是則先調用postProcessBeanDefinitionRegistry()方法,這裏調用的有:
- CachingMetadataReaderFactoryPostProcessor
- ConfigurationWarningsPostProcessor
3、然後調用實現了PriorityOrdered的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry()方法,這裏調用的有:
- ConfigurationClassPostProcessor
4、調用實現Ordered的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry(),這裏沒有。
5、調用所有其他BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry(),這裏也沒有。
6、在調用BeanDefinitionRegistryPostProcessors的postProcessBeanFactory()方法,這裏調用的有:
- CachingMetadataReaderFactoryPostProcessor
- ConfigurationWarningsPostProcessor
- ConfigurationClassPostProcessor
- PropertySourceOrderingPostProcessor
7、調用實現PriorityOrdered的BeanFactoryPostProcessor的postProcessBeanFactory()方法,這裏調用的有:
- PropertySourcesPlaceholderConfigurer
8、調用實現Ordered的BeanFactoryPostProcessor的postProcessBeanFactory()方法,這裏沒有。
9、調用所有其他BeanFactoryPostProcessor的postProcessBeanFactory()方法,這裏調用的有:
- EventListenerMethodProcessor
- ConfigurationBeanFactoryMetadata
- PreserveErrorControllerTargetClassPostProcessor
10、最後,清除緩存的合併bean定義,因爲後處理器可能修改了原始元數據,例如替換值中的佔位符…
postProcessBeanDefinitionRegistry()方法 | |
CachingMetadataReaderFactoryPostProcessor | 註冊了一個SharedMetadataReaderFactoryBean,並配置到ConfigurationClassPostProcessor |
ConfigurationWarningsPostProcessor | 檢查@ComponentScan設置的包是否存在問題,並打印日誌 |
ConfigurationClassPostProcessor | 處理@Configuration配置類,這裏的內容不止是我簡單的這一句話,裏面還有很多東西 |
postProcessBeanFactory()方法 | |
CachingMetadataReaderFactoryPostProcessor | 空 |
ConfigurationWarningsPostProcessor | 空 |
ConfigurationClassPostProcessor | 通過cglib 增強的子類替換候選的full配置類,是否爲full配置類的具體判斷邏輯見
ConfigurationClassUtils.isFullConfigurationCandidate()方法 |
PropertySourceOrderingPostProcessor | |
EventListenerMethodProcessor | 通過beanFactory得到DefaultEventListenerFactory並設置,該類實現了SmartInitializingSingleton接口,重寫了afterSingletonsInstantiated方法,會在所有單實例bean實例化之後執行,就是後面的finishBeanFactoryInitialization()方法會進行回調,在afterSingletonsInstantiated方法中會處理帶有@EventListener註解的方法,用postProcessBeanFactory()設置的eventListenerFactories創建listener,添加到上下文 |
ConfigurationBeanFactoryMetadata | 在bean工廠初始化期間存儲@bean定義元數據 |
PreserveErrorControllerTargetClassPostProcessor |
6、註冊BeanPostProcessor
這裏同樣根據實現priorityordered、ordered和其他對beanPostprocessor進行分類。
首先,註冊實現PriorityOrdered的BeanPostProcessor:
- ConfigurationPropertiesBindingPostProcessor
- CommonAnnotationBeanPostProcessor
- AutowiredAnnotationBeanPostProcessor
接下來,註冊實現Ordered的beanPostProcessor:
- MethodValidationPostProcessor
現在,註冊所有常規的beanPostProcessor:
- WebServerFactoryCustomizerBeanPostProcessor
- ErrorPageRegistrarBeanPostProcessor
最後,重新註冊所有內部BeanPostProcessor。
- AutowiredAnnotationBeanPostProcessor
- CommonAnnotationBeanPostProcessor
在後面再註冊了ApplicationListenerDetector。
這裏流程跟上面調用BeanFactoryPostProcessor是差不多的,自己看吧。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
在哪裏應用BeanPostProcessor呢?
簡單說一下,doGetBean方法----getSingleton----createBean----doCreateBean----initializeBean。會在bean初始化之前應用。
7、初始化信息源
這裏就是註冊一個DelegatingMessageSource。
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
8、註冊SimpleApplicationEventMulticaster
註冊一個SimpleApplicationEventMulticaster,不多說,前面說了。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
//applicationEventMulticaster
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
9、onRefresh()
初始化特定上下文子類中的其他特殊bean。一個模板方法,不同的Spring容器做不同的事情。在這裏會調用createWebServer()去創建內置的Servlet容器。創建Servlet容器的過程中做的事情就比較多了。不做詳細介紹。
最開始入門就介紹了Spring Boot支持以下嵌入式servlet容器:
Name | Servlet Version |
---|---|
Tomcat 9.0 |
4.0 |
Jetty 9.4 |
3.1 |
Undertow 2.0 |
4.0 |
//ServletWebServerApplicationContext.java
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
默認的是Tomcat,其中customizeConnector()方法就是定製內嵌的Tomcat ,如果你實現了TomcatConnectorCustomizer接口並重寫了customize方法。
下面的日誌是不是很熟悉了。
10、註冊Listener
protected void registerListeners() {
// 得到多播器,添加Listener
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 這裏流程跟上面一樣了
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 發佈早期事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
11、完成beanFactory初始化,初始化所有剩餘的單例bean
具體的Bean初始化流程參考:https://www.cnblogs.com/xrq730/p/6361578.html
會在這一步調用SmartInitializingSingleton接口的afterSingletonsInstantiated()方法。
12、完成刷新
發佈ContextRefreshedEvent,這裏發佈事件調用的是AbstractApplicationContext的publishEvent()方法,不過最終發佈事件還是調用的多播器EventMulticaster的multicastEvent()方法,也就是前面說過的事件發佈方法。
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
DelegatingApplicationListener:沒做事
ConditionEvaluationReportListener:日誌自動配置報告
ClearCachesApplicationListener:在加載上下文後清除緩存。
SharedMetadataReaderFactoryBean:刪除所有緩存的類元數據。
ResourceUrlProvider
最後啓動Tomcat,發佈ServletWebServerInitializedEvent事件。
SpringApplicationAdminMXBeanRegistrar:更改embeddedWebApplication爲true,嵌入式web程序。
DelegatingApplicationListener:無
ServerPortInfoApplicationContextInitializer:這個前面有提過的,設置了webserver實際監聽的端口值,如果該事件的WebServerApplicationContext具有NameSpace,則使用它來構造屬性名,否則使用缺省值server。
就到這裏,後面都是清理緩存,感覺身體被掏空......