Spring IOC(1)----容器重新整理(refresh())之前
首先本次分析是基於註解形式的,想來xml格式的原理都是類似的。
首先說一下什麼是Bean定義(beandefinition):bean定義並不是例項化的bean,而是bean物件的一些資訊,根據這些定義的資訊最後來初始化bean。比方說就是一些類的資訊,還有我們配置的該例項的資訊(是否懶載入,單例還是多例,作用域等等資訊)。
進入正題:
AnnotationConfigApplicationContext構造方法傳入一個主配置類,那麼就從該構造方法進去。
一、我們先來看在容器重新整理(refresh())之前,都幹了什麼。
1.this()首先會呼叫無參構造,進而呼叫父類的無參構造,初始化beanFactory(DefaultListableBeanFactory),再者初始化註解模式下的bean定義讀取器,classPath型別的bean定義掃描器;
2.register(annotatedClasses),基於上面初始化的bean定義讀取器去解析註冊我們自己的配置類資訊到容器中。
具體的流程圖如下:
完成了這些準備工作。refresh()裡面就會例項化具體的bean了。
二、兩個個擴充套件點
1. BeanDefinitionRegistryPostProcessor
Bean定義處理器,在註冊bean定義的時候呼叫,可以自己註冊新的bean定義
先直接通過上下文物件獲取一個student,會報錯,沒有對應的bean定義
實現自己的Bean定義處理器
MyBeanDefinitionRegistryPostProcessor
package com.nijunyang.spring; import com.nijunyang.spring.model.Student; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.stereotype.Component; /** * @author: create by nijunyang * @date:2019/10/6 */ @Component public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { //bean定義註冊處理器,在註冊bean定義的時候呼叫,可以自己註冊新的bean定義,比如Student @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println("bean定義的資料量:"+registry.getBeanDefinitionCount()); RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class); //註冊一個名為student的bean定義進去 registry.registerBeanDefinition("student", rootBeanDefinition); System.out.println("bean定義的資料量:"+registry.getBeanDefinitionCount()); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }
注意需要加上@Component,並且主配置指定掃描的包將自己定義的類載入進去
MainConfig
package com.nijunyang.spring; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * @author: create by nijunyang * @date:2019/10/6 */ @Configuration @ComponentScan(basePackages = "com.nijunyang.spring") public class MainConfig { }
正常獲取bean。
2.BeanFactoryPostProcessor
BeanFactory後置處理器,註冊了bean定義之後呼叫,可以修改bean定義,比如實現一個自己的BeanFactory後置處理器,把某個bean設定成懶載入。
斷點執行1步驟中的程式碼,發現student不是懶載入的
實現自己的BeanFactory後置處理器,將student設定成懶載入
MyBeanFactoryPostProcessor
package com.nijunyang.spring; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Component; /** * @author: create by nijunyang * @date:2019/10/6 */ @Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { //註冊了bean定義之後呼叫,可以修改bean定義,比如把student設定成懶載入 @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { for(String name : beanFactory.getBeanDefinitionNames()) { if("student".equals(name)) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name); beanDefinition.setLazyInit(true); } } } }
同樣斷點執行,發現student不會馬上被初始化了
&n