加載機制:
ClassPathXmlApplicationContext:應用程序的上下文,將普通路徑解析爲類(classpath)路徑資源名稱
// 多個配置文件的情況下,後加載的bean會覆蓋先前定義好的bean,這樣做的目的是爲了通過額外的XML文件來特意重寫某個Bean
public ClassPathXmlApplicationContext(String[] configLocations, booleanrefresh, ApplicationContext parent)
throwsBeansException {
//
super(parent);
// 解析 bean.xml 文件
setConfigLocations(configLocations);
if (refresh){
refresh();
}
}
DefaultBeanDefinitionDocumentReader: BeanDefinitionDocumentReader 接口的默認實現根據“spring-beans” DTD和XSD格式讀取bean定義(Spring的默認XML bean定義格式)。
// 在 {@code <beans />} 元素中註冊每個定義好的bean
// 同時會解析 beans 的 profile
-> protectedvoid doRegisterBeanDefinitions(Element root);
// 根據“spring-beans”XSD解析bean定義
-> public voidregisterBeanDefinitions(Document doc, XmlReaderContextreaderContext);
// 解析 root 節點下的其它節點 import","alias", "bean".
-> protectedvoid parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate);
-> 判斷當前 ele 是什麼節點 ,然後在跳轉到對應的方法中處理
private voidparseDefaultElement(Element ele,BeanDefinitionParserDelegate delegate);
|
|--->processBeanDefinition(ele, delegate);
1.InputStreamSource 封裝了任何能返回 InputStream 的類,比如 File ClassPath Byte Array 等
-> booleanexists(); 判斷文件是否存在
-> booleanisReadable(); 文件是否可讀/權限
-> booleanisOpen(); 文件是否打開狀態
-> 此外還提供了 URL URI File 類型轉換,以及獲取lastModified屬性,文件名,出錯信息等
1.加載 bean.xml 文件
-> ConfigReader:用於讀取及驗證配置文件是否正確(XML的XSD驗證)
-> ReflectionUtil:根據 bean.xml 中的配置進行反射實例化對象
2.解析 bean.xml 標籤,找到對應 bean 的配置,實例化對象
Spring 核心類
-> DefaultListableBeanFactory(核心類/註冊及Bean的默認實現) 擴展了 XmlBeanDefinitionReader(自定義的XML讀取器,實現個性化的BeanDefinitionReader讀取)
->XmlBeanDefinitionReader XML文件讀取
->AbstractBeanDefinitionReader
//讀取 bean 定義時的環境 比如 @Profile("dev") 這種
//同時默認加載systemPropertiessystemEnvironment 系統配置及修通變量 - 詳請(StandardEnvironment.class)
->protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry);
//從指定的XML文件加載bean定義。
publicint loadBeanDefinitions(EncodedResource encodedResource) throwsBeanDefinitionStoreException;
->BeanDefinitionReader
->ResourceLoader:資源加載器,應用於根據給定資源地址返回對應資源(Resource)
->DefaultResourceLoader:ResourceLoader接口的默認實現。
->AbstractApplicationContext
//
->public void refresh();
->AbstractRefreshableApplicationContext
*刷新上下文
*如果之前存在 bean工廠,關閉以前的bean工廠 (destroyBeans() | closeBeanFactory())
*爲上下文生命週期的下一階段初始化一個新鮮的bean工廠。
->protected final void refreshBeanFactory()
->DefaultListableBeanFactory beanFactory = createBeanFactory(); 然後創建一個全新的 BeanFactory
->protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
->AbstractXmlApplicationContext
*通過 XmlBeanDefinitionReader 加載定義好的 Bean
->protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
->AbstractRefreshableConfigApplicationContext
*以init-param風格設置此應用程序上下文的配置位置,
*即用不同的位置用逗號,分號或空格分開。
*<p>如果沒有設置,則實現可以使用默認值。
->public void setConfigLocations(String... locations)
->AbstractBeanDefinitionRead:實現下面倆個接口
->BeanDefinitionReader:資源轉換 BeanDefinition 的各個功能
->EnvironmentCapable:獲取 Environment 方法
->DocumentLoader:從資源文件加載到轉換爲 Document 功能
—>BeanDefinitionDocumentRead:讀取Document並註冊 BeanDefinition
->BeanDefinitionParserDelegate:解析 Element 各種方法
//根據 bean元素的屬性初始化的bean定義
//解析 Element(比如 <bean />) 會設置 scope lazy-init 等 ,
//默認屬性參考“DocumentDefaultsDefinition”
->public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, StringbeanName,BeanDefinition containingBean, AbstractBeanDefinition bd);
-> 繼承AbstractAutowireCapableBeanFactory :綜合 AbstractBeanFactory 並對接口 Autowire CapableBeanFactory 進行實現
// 確定指定 bean 的目標類型
->protected Class<?> determineTargetType(String beanName,RootBeanDefinition mbd, Class<?>... typesToMatch)
/**
* 使用“深拷貝”來拷貝 bean工廠中正常運行的bean 目的是防止因直接修改“引用”而導致 bean工廠中維護的 bean對象被修改
* @param beanName 爲了獲得更準確的異常信息而傳遞的bean名稱
* @param mbd 合併後的bean
* @param bw 使用 BeanWrapper 包裝目標對象 bw.setPropertyValues(newMutablePropertyValues(deepCopy));
* @param pvs 新的屬性值
*/
->protected void applyPropertyValues(String beanName, BeanDefinition mbd,BeanWrapper bw, PropertyValues pvs)
/**
* 使用合適的實例化策略來構建指定的 bean(工廠方法 | 構造函數 | 自動裝配)
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
->protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinitionmbd, Object[] args);
// 使用 BeanWrapper 實例化 bean 定義的屬性值
->protected void populateBean(String beanName, RootBeanDefinition mbd,BeanWrapper bw)
|
|--->PropertyValues pvs = mbd.getPropertyValues(); 拿到 bean 中所有 <property name="id" value="1"/> 的 Key 與 Value
-> 實現ConfigurableListableBeanFactory 接口
-> 實現 BeanDefinitionRegistry 接口
1、在spring同一個配置文件中,不能存在id相同的兩個bean,否則會報錯。
2、在兩個不同的spring配置文件中,可以存在id相同的兩個bean,啓動時,不會報錯。這是因爲spring ioc容器在加載bean的過程中,
類 DefaultListableBeanFactory 會對id相同的bean進行處理:後加載的配置文件的bean,覆蓋先加載的配置文件的bean。
DefaultListableBeanFactory類中,有個屬性allowBeanDefinitionOverriding,默認值爲true,該值就是用來指定出現兩個bean的id相同的情況下,如何進行處理。如果該值爲false,則不會進行覆蓋,而是拋出異常。
=>DefaultListableBeanFactory
// 獲取 Bean 類型的名稱、比如是否爲 FactoryBean
->private String[] doGetBeanNamesForType(ResolvableType type, booleanincludeNonSingletons, boolean allowEagerInit);
AliasRegistry :定義對 alias 的簡單增刪改操作
->SimpleAliasRegistry:`AliasRegistry`接口的實現,使用Map緩存alias
//@param name 用戶指定的名稱
//@return 被轉換的名字
->public String canonicalName(String name) 別名解析 : 根據原始名稱,將別名解析爲規範名稱。
SingletonBeanRegistry:單例Bean容器(註冊/獲取)
-> DefaultSingletonBeanRegistry:`SingletonBeanRegistry`的默認實現
/**根據 beanName 返回指定 bean 的單例對象,如果不存在返回 null
*/
->protected Object getSingleton(String beanName, boolean allowEarlyReference)
BeanFactory:Bean的相關屬性
->HierarchicalBeanFactory:繼承 BeanFactory ,在其基礎之上增加了對 parentFactory 的支持
BeanDefinition:
->BeanDefinitionRegistry:定義對 BeanDefinition 的相關操作
FactoryBeanRegistrySupport:在DefaultSinglentBeanRegistry基礎上增加了 FactoryBean 的特殊處理
ConfigurableBeanFactory:提供配置 BeanFactory 的各種方法
ListableBeanFactory:根據條件獲取 Bean的配置清單
AbstractBeanFactory:綜合 FactoryBeanRegistrySupport 和 ConfigurableListableBeanFactory 的功能
解析Bean以及將它存儲在 mergedBeanDefinitions 中緩存起來
->protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throwsBeansException
初始化自定義的PropertyEditorRegistry
->protected void registerCustomEditors(PropertyEditorRegistry registry)
*將指定的 bean 添加到該工廠中的一次性bean的列表中,
*註冊其DisposableBean接口和/或給定的銷燬方法
*在工廠關機時被調用(如適用)。只適用於單例對象。
->protected void registerDisposableBeanIfNecessary(String beanName, Object bean,RootBeanDefinition mbd)
->protected RootBeanDefinition getMergedBeanDefinition(String beanName,BeanDefinition bd, BeanDefinition containingBd) throwsBeanDefinitionStoreException
-> 默認 RootBeanDefinition mbd = null;
-> 判斷了Bean是否存在, 緩存(mergedBeanDefinitions)存在則從緩存中直接提取
if(containingBd == null) {
mbd= this.mergedBeanDefinitions.get(beanName);
}
->單例分配| | 由於 <bean id="person" class="com.battcn.bean.Person"/> 並未指定scope那麼提取系統默認的RootBeanDefinition.SCOPE_SINGLETON值
if(!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
->SimpleInstantiationStrategy:在BeanFactory中使用的簡單對象實例化策略。儘管它提供了子類的鉤子以覆蓋添加方法注入支持,例如通過覆蓋方法。但是不支持方法注入
// 在此處通過 BeanUtils.instantiateClass(constructorToUse); 反射實例化出對象
// public Person() {
// System.out.println("init");
// }
// 在調用完 BeanUtils.instantiateClass(constructorToUse); 後就可以看到日誌輸出的 init
-> publicObject instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner);
Spring
-> lazy-init="default | true | false"
當我們使用lazy-init = "default"作爲元素中的一個屬性時,容器拾取由元素的default-lazy-init ="true | false"屬性指定的值,並將其用作lazy-init ="true | false"。
如果元素中不存在default-lazy-init 屬性,則元素中的lazy-init =“default” 的行爲就像lazy-init-“false” 一樣。
結合 scope = "singleton" 可以理解爲懶漢單例模式與餓漢單例模式區別
Spring 的Bean默認單例
-> scope="singleton |prototype"默認 singleton = 單例 prototype = 多實例