SpringBoot(十四)啓動流程分析之refreshContext()

SpringBoot版本:2.1.1     ==》啓動流程分析彙總

接上篇Spring Boot 2.1.1(十三)啓動流程分析之準備應用上下文

目錄

流程分析 

1、準備刷新

 子類prepareRefresh()方法

父類prepareRefresh()方法

2、通知子類刷新內部bean工廠

3、準備bean工廠

4、允許上下文子類對bean工廠進行後置處理

5、調用已註冊的BeanFactoryPostProcessors Bean

先調用BeanDefinitionRegistryPostProcessors

再調用BeanFactoryPostProcessor

6、註冊BeanPostProcessor

7、初始化信息源

8、註冊SimpleApplicationEventMulticaster

9、onRefresh()

10、註冊Listener

11、完成beanFactory初始化,初始化所有剩餘的單例bean

12、完成刷新


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,將會先執行:

  1. CachingMetadataReaderFactoryPostProcessor
  2. 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、調用實現PriorityOrderedBeanFactoryPostProcessorpostProcessBeanFactory()方法,這裏調用的有:

  • 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。

就到這裏,後面都是清理緩存,感覺身體被掏空......

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章