spring知識總結

加載機制:

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” DTDXSD格式讀取bean定義Spring的默認XML bean定義格式)。

        

         // {@code <beans />} 元素中註冊每個定義好的bean

         // 同時會解析 beans profile

         -> protectedvoid doRegisterBeanDefinitions(Element root);

        

         // 根據spring-beansXSD解析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:用於讀取及驗證配置文件是否正確(XMLXSD驗證)

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

                                   ->DefaultResourceLoaderResourceLoader接口的默認實現。

                                            ->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,該值就是用來指定出現兩個beanid相同的情況下,如何進行處理。如果該值爲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)

                  

        

         BeanFactoryBean的相關屬性

                 ->HierarchicalBeanFactory:繼承 BeanFactory ,在其基礎之上增加了對 parentFactory 的支持

                

         BeanDefinition

                 ->BeanDefinitionRegistry定義對 BeanDefinition 的相關操作

 

         FactoryBeanRegistrySupportDefaultSinglentBeanRegistry基礎上增加了 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 = 多實例

 

發佈了25 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章