【Spring原始碼閱讀】 Spring容器初始化流程
文章目錄
- refresh方法原始碼
- prepareRefresh實現
- obtainFreshBeanFactory實現
- refreshBeanFactory方法實現
- prepareBeanFactory方法實現
- invokeBeanFactoryPostProcessors方法實現
- registerBeanPostProcessors方法實現
- initMessageSource方法實現
- initApplicationEventMulticaster方法實現
- registerListeners方法實現
- finishBeanFactoryInitialization方法實現
- finishRefresh方法實現
- destroyBeans方法實現
以下面測試程式碼為例:
public class BaseTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
TestBean testBean = context.getBean("testBean", TestBean.class );
testBean.echo();
}
}
執行後,首先呼叫ClassPathXmlApplicationContext建構函式
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
具體呼叫以下構造方法:
// configLocations = new String[] {configLocation}
// refresh = true,表示要重新整理初始化容器
// parent = null,表示不存在父容器
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
// 通過層層呼叫父建構函式,主要初始化了this.resourcePatternResolver=new PathMatchingResourcePatternResolver(this);後續可以通過適配符尋找符合條件的java類
super(parent);
// 遍歷解析傳入的配置檔案路徑,將路徑中的佔位符替換成相關的環境變數。
setConfigLocations(configLocations);
if (refresh) { // true
// 呼叫父類AbstractApplicationContext中定義的refresh方法,完成Spring容器和應用上下文的建立工作。
refresh();
}
}
refresh方法原始碼
具體refresh程式碼如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 供子類拓展,新增建立前必需屬性,校驗如果必需屬性不存在則丟擲MissingRequiredPropertiesException異常
prepareRefresh();
// 呼叫子類實現方法獲取(建立或重新整理)BeanFacotry容器,對於ClassPathXmlApplicationContext,主要呼叫了AbstractRefreshableApplicationContext中實現的方法
// 在這裡,將xml配置檔案中 的Bean解析成了一個個BeanDefinition,建立一個beanName-> beanDefinition 的 map
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 設定類載入器,spel解析器,屬性編輯解析器等,忽略特定介面的依賴註冊(在特定時刻相關Bean再完成注入),註冊一些系統Bean供依賴注入使用。
prepareBeanFactory(beanFactory);
try {
// BeanFactory建立完的後置處理。當前為空實現,供子類拓展
postProcessBeanFactory(beanFactory);
// 呼叫BeanFacotry的相關後置處理器,如果實現了Order相關介面,會先進行排序。
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊相關BeanPostProcessor,供Bean生成前後呼叫。
registerBeanPostProcessors(beanFactory);
// 初始化國際化資訊源
initMessageSource();
// 初始化Spring相關上下文時間廣播器
initApplicationEventMulticaster();
// 模版方法供子類實現,用於初始化一些特殊Bean配置等
onRefresh();
// 註冊實現了ApplicationListener介面的事件監聽器,用於後續廣播器廣播事件
registerListeners();
// BeanFactory初始化完成時呼叫,初始ConversionService Bean,凍結beanFactory配置,並開始建立BeanFactory中所有非懶載入的單例Bean
finishBeanFactoryInitialization(beanFactory);
// 初始化Lifecycle處理器,呼叫onRefresh方法,廣播ContextRefreshedEvent。
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;
}
}
}
prepareRefresh實現
下面先粗略講解refresh函式下每一步操作的原始碼實現:
// 供子類拓展,新增建立前必需屬性,校驗如果必需屬性不存在則丟擲MissingRequiredPropertiesException異常
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 內部是一個空實現,主要供子類拓展自己ApplicationContext,設定必需的屬性
initPropertySources();
// 校驗必需的屬性是否存在,具體參考下面的程式碼
getEnvironment().validateRequiredProperties();
}
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
for (String key : this.requiredProperties) {
// 如果存在屬性缺失,記錄下來
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
// 存在缺失屬性則丟擲異常
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}
obtainFreshBeanFactory實現
// 呼叫子類實現方法獲取(建立或重新整理)BeanFacotry容器,對於ClassPathXmlApplicationContext,主要呼叫了AbstractRefreshableApplicationContext中實現的方法
// 在這裡,將xml配置檔案中 的Bean解析成了一個個BeanDefinition,建立一個beanName-> beanDefinition 的 map
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 重新整理初始化BeanFactory,核心在這一步
refreshBeanFactory();
// 獲取上一步初始化的BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
refreshBeanFactory方法實現
具體實現位於AbstractRefreshableApplicationContext類下:
protected final void refreshBeanFactory() throws BeansException {
// 如果已經存在,先銷燬存在的
if (hasBeanFactory()) {
// 銷燬工廠的所有相關單例Bean
destroyBeans();
// 清理工廠相關配置
closeBeanFactory();
}
try {
// 通過new DefaultListableBeanFactory(getInternalParentBeanFactory())建立一個空工廠例項
// 其中getInternalParentBeanFactory()=null
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 記錄對映id -> DefaultListableBeanFactory到一個靜態Map
beanFactory.setSerializationId(getId());
// 定製Bean工廠,主要供使用者自定義子類拓展是否允許BeanDefinition重寫(預設true)、迴圈引用(預設true)等功能。
customizeBeanFactory(beanFactory);
// 讀取xml配置,將配置中定義的Bean以BeanDefinition封裝儲存到beanFactory中。
loadBeanDefinitions(beanFactory);
// 記錄引用。
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
prepareBeanFactory方法實現
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 設定類載入器,spel解析器,屬性編輯解析器等 context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//忽略特定介面的實現類依賴注入,在Spring特定初始實現了這些相關介面的Bean的特定時刻再統一完成注入,避免重複注入等問題。具體是在ApplicationContextAwareProcessor中完成
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型別,則注入beanFactory物件,如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext型別則注入當前物件(applicationContext物件)
// 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);
// 判斷是否定義了名為loadTimeWeaver的bean,如果定義了則新增loadTimeWeaver功能的beanPostProcessor擴充套件,並且建立一個臨時的classLoader來讓其處理真正的bean。spring的loadTimeWeaver主要是通過 instrumentation 的動態位元組碼增強在裝載期注入依賴
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()));
}
// 註冊環境相關的Bean到容器中,後續便支援這些Bean的依賴注入相關操作
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
invokeBeanFactoryPostProcessors方法實現
總體方法實現邏輯:呼叫所有註冊在Spring容器中的實現BeanFactoryPostProcessors介面Bean的postProcessBeanFactory方法。如果這些BeanFactoryPostProcessor實現了Order介面,會先進行排序再依次呼叫。通過這些BeanFactoryPostProcessors,可以對BeanFacotry進一步定製,如修改裡面的Bean屬性等。
// 有兩種方式新增具體的後置處理器。
// 一種是程式設計式新增:`context.addBeanFactoryPostProcessor`,這個通過getBeanFactoryPostProcessors獲取
// 另一種是通過xml配置`<bean class="com.xx.XxxBeanFactoryPostProcessor" />`,這個通過beanFactory.getBeansOfType獲取
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Set<String> processedBeans = new HashSet<String>();
// 如果是BeanDefinitionRegistry的實現類,需要獲取出來,呼叫其中的postProcessBeanDefinitionRegistry方法
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
// 如果是BeanDefinitionRegistryPostProcessor的例項,還需要呼叫postProcessBeanDefinitionRegistry()方法
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// 呼叫基於getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false)獲取的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry,注意這裡根據實現Order介面進行優先順序排序
Map<String, BeanDefinitionRegistryPostProcessor> beanMap = beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
OrderComparator.sort(registryPostProcessorBeans);
for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
// 呼叫上述方法的基於BeanFactoryPostProcessor介面的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
processedBeans.addAll(beanMap.keySet());
}
else {
// 僅呼叫通過程式設計註冊的處理器方法
invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
}
// 根據Type=BeanFactoryPostProcessor獲取相關的後置處理器,由於BeanDefinitionRegistryPostProcessor屬於
String[] postProcessorNames =BeanFactoryPostProcessor的子類,所以後面會過濾掉上面呼叫過的processedBeans
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 區分實現了PriorityOrdered,Ordered等介面和未實現Order介面的後置處理器,依次排序後呼叫。
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
OrderComparator.sort(priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
OrderComparator.sort(orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
}
// 具體invokeBeanFactoryPostProcessors方法實現如下:
private void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
// 依次遍歷呼叫其中的postProcessBeanFactory
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
registerBeanPostProcessors方法實現
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 根據BeanPostProcessor型別獲取容器中具體的BeanNames
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 區分實現了PriorityOrdered,Ordered等介面和未實現Order介面的後置處理器,依次排序後新增到ArrayList,最後呼叫時確保呼叫順序。
// 如果是MergedBeanDefinitionPostProcessor的例項,會收集起來排序後再次重新註冊,、
// MergedBeanDefinitionPostProcessor中定義了postProcessMergedBeanDefinition方法
//會在建立Bean例項後,填充Bean屬性和呼叫其中所有後置處理器的postProcessBeforeInitialization前呼叫postProcessMergedBeanDefinition,
//用來提供機會修改MergedBeanDefinition
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.
相關推薦
【spring原始碼分析】IOC容器初始化(二)
前言:在【spring原始碼分析】IOC容器初始化(一)中已經分析了匯入bean階段,本篇接著分析bean解析階段。
1.解析bean程式呼叫鏈
同樣,先給出解析bean的程式呼叫鏈:
根據程式呼叫鏈,整理出在解析bean過程中主要涉及的類和相關方法。
2.解析bean原始碼分
【Spring原始碼閱讀】 Spring容器初始化流程
文章目錄
refresh方法原始碼
prepareRefresh實現
obtainFreshBeanFactory實現
refreshBeanFactory方法實現
prepareBeanFactory方法實現
invokeBeanFa
【Spring原始碼閱讀】BeanDefinition原理與載入流程
BeanDefinition介面定義及其相關子類實現
在Spring容器初始化過程中,Spring會將配置檔案中配置的Java類封裝成一個個BeanDefinition。 BeanDefinition儲存了具體代表Bean的類,並通過實現了AttributeAccessor介面定義了
【Spring原始碼閱讀】Spring原始碼閱讀環境搭建
閱讀Spring原始碼,我們可以通過以下兩種方式:
直接在Idea/Eclipse上建立自己的java maven/gradle專案,匯入Spring特定版本依賴Jar和原始碼,直接執行測試程式碼,逐步除錯閱讀
從github直接獲取Spring原始碼專案,基於Spri
【Spring Framework 深入】—— IoC容器初始化 -> Bean定義資源的Resource定位
基本概念
ApplicationContext 繼承體系
本文主要關注ApplicationContext的繼承體系,至於BeanFactory的分支,以後再研究。
BeanFactory or ApplicationContext?
Bea
【Spring原始碼閱讀】IOC核心容器基礎和繼承體系結構
BeanFactory
BeanFacotry作為Spring的根容器物件,提供了對Bean的基礎操作功能,包括例項化、配置、管理Bean等。
ApplicationContext
ApplicationContext對BeanFactory進行了進一步地封裝,內建了Bean
【Spring原始碼閱讀】 DefaultListableBeanFactory繼承結構講解分析
在基於ClassPathXmlApplicationContext建立BeanFactory時,我們從程式碼裡看到,建立的BeanFactory的型別是DefaultListableBeanFactory。 下面我們來分析下DefaultListableBeanFactory的繼承結構,
【Spring原始碼閱讀】populateBean實現 依賴注入原始碼解析
在完成Bean例項化後,Spring容器會給這個Bean注入相關的依賴Bean,在原始碼中,這一步通過類AbstractAutowireCapableBeanFactory中的populateBean方法完成。
測試程式碼
下面開始進入原始碼分析之前,先基於以下例項進行:
/
【Spring原始碼閱讀】 preInstantiateSingletons方法分析,單例Bean獲取/例項化流程
在初始化ClassPathXmlApplicatonContext過程中,核心初始化邏輯在AbstractApplicationContext的refresh函式中:
public void refresh() throws BeansException, IllegalStateE
【Spring】- IOC容器初始化過程
浪費了“黃金五年”的Java程式設計師,還有救嗎?
>>>
Spring IOC原始碼詳解之容器初始化
可以進入parseBeanDefinitionElement方法中,裡面詳細講了Bean元素是如何解析的。
//解析<Bean>元素的入口
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
【java原始碼閱讀】Map介面
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to l
【GAN ZOO閱讀】模式正則化的生成對抗網路 MODE REGULARIZED GENERATIVE ADVERSARIAL NETWORKS
原文地址: https://arxiv.org/abs/1612.02136 引用之請註明出處。
Tong Che 1,Yanran Li 2 3,Athul Paul Jacob 1,Yoshua Bengio 1,Wenjie Li 2
1 蒙特利爾學習演算法
【JDK原始碼分析】01-物件序列化ObjectOutputStream
上一篇文章提到反序列化列舉類仍是單例,而普通類物件不是單例,下面我們先分析一下序列化過程,序列化就是呼叫ObjectOutStream的物件的writeObject方法。我們先看一下序列化涉及的比較重要的一個ObjectStreamClass,JDK中的描述是:類的序列化描述
SpringBoot框架——從SpringBoot看IoC容器初始化流程之方法分析
目錄
一、概觀Spring Boot
二、Spring Boot應用初始化
2.1 初始化入口
2.2 SpringApplication的run方法
2.3 方法分析
三、容器建立與初始化
3.1 creatApplicationContext()方法
3.2 prepareContext(co
【Spring MVC】DispatcherServlet詳解(容器初始化超詳細過程原始碼分析)
DispatcherServlet類相關的結構圖DispatcherServlet的初始化程式DispatcherServlet初始化了什麼,可以在其initStrategies()方法中知曉,這個方法如下: protected void initStrategies(App
【Spring原始碼解析】—— 結合SpringMVC過程理解IOC容器初始化之註解部分探究
前面的文章寫了xml中直接配置bean進行IOC的過程解析,接下來會針對註解進行IOC容器初始化的過程解析
因為會與之前的內容存在部分重疊,因此會針對相同的部分簡略帶過,針對不同的部分做重點說明:
一、Xml的配置和程式碼中的註解配置:
applicationContext.xml配置新
【Spring原始碼解析(一)】Idea搭建Spring原始碼閱讀環境
準備階段
Idea
Gradle
Git
jdk
詳細步驟
以上工具安裝好,這裡主要記錄一下Git和Gradle,工作一直都是用的svn和Maven,所以對於Git和Gradle瞭解的不算多。
(1) Gradle安裝
Gradle的安裝很簡單,和
Spring原始碼分析【1】-Tomcat的初始化
org.apache.catalina.startup.ContextConfig.configureStart()
org.apache.catalina.startup.ContextConfig.webConfig()
進入org.apache.catali
spring原始碼學習之路---IOC容器初始化要義之bean定義載入(四)
上章說到要帶各位去看看bean定義載入的要義,其實就是loadBeanDefinitions這個方法的具體實現步驟,下面我們跟隨這個方法去看下它到底是如何載入bean定義的。
上面是我擷取的實現了loadBeanDefinitions的類級別截圖,loadBeanDefinit