Spring IOC 源碼解析
控制反轉(IoC)
控制反轉(IoC)原理的Spring Framework實作。IoC也稱為依賴注入(DI)。這是一個過程,通過這個過程,對象隻能通過構造函數參數,工廠方法的參數或在構造或從工廠方法傳回後在對象執行個體上設定的屬性來定義它們的依賴關系(即,它們使用的其他對象)。 。然後容器在建立bean時注入這些依賴項。此過程基本上是bean本身的逆(是以名稱,控制反轉),通過使用類的直接構造或諸如服務定位器模式的機制來控制其依賴關系的執行個體化或位置。(官方文檔5.x說明)。所謂IoC,對于spring架構來說,就是由spring來負責控制對象的生命周期和對象間的關系。
基于XML的中繼資料不是唯一允許的配置中繼資料形式。Spring IoC容器本身完全與實際編寫此配置中繼資料的格式分離。目前,許多開發人員為其Spring應用程式選擇 基于Java的配置。
有關在Spring容器中使用其他形式的中繼資料的資訊,請參閱:
- 基于注釋的配置:Spring 2.5引入了對基于注釋的配置中繼資料的支援。(我這裡不解釋)
- 基于Java的配置:從Spring 3.0開始,Spring JavaConfig項目提供的許多功能成為核心Spring Framework的一部分。是以,您可以使用Java而不是XML檔案在應用程式類外部定義bean。要使用這些新功能,請參閱 @Configuration, @Bean, @Import,和@DependsOn注釋。
首先了解什麼是spring Bean?spring的bean是具有完整的spring生命周期的對象。
那spring生命周期的經曆了什麼呢?
初始化、屬性指派、執行個體化、銷毀。
spring容器可以稱為spring上下文或者spring環境。
spring容器包含各種元件,如:bean工廠、單例池、讀取器、掃描器、處理器、後置處理器等
這裡将會解釋一下:
bean的初始化和執行個體化:
bean的初始化:一個對象被new出來,完成屬性方法填充,最後生命周期回調方法執行
bean的執行個體化:一個類變成bean的過程
Spring的生命周期
Spring的9個後置處理器
流傳的大部分部落格對spring生命周期的看法
不知道Spring官方對Bean的生命問題是否有明确的定義或者解析,但是Spring In Action以及市面上流傳的大部分部落格是這樣的:
- 執行個體化Bean對象,這個時候Bean的對象是非常低級的,基本不能夠被我們使用,因為連最基本的屬性都沒有設定,可以了解為連Autowired注解都是沒有解析的;
- 填充屬性,當做完這一步,Bean對象基本是完整的了,可以了解為Autowired注解已經解析完畢,依賴注入完成了;
- 如果Bean實作了BeanNameAware接口,則調用setBeanName方法;
- 如果Bean實作了BeanClassLoaderAware接口,則調用setBeanClassLoader方法;
- 如果Bean實作了BeanFactoryAware接口,則調用setBeanFactory方法;
- 調用BeanPostProcessor的postProcessBeforeInitialization方法;
- 如果Bean實作了InitializingBean接口,調用afterPropertiesSet方法;
- 如果Bean定義了init-method方法,則調用Bean的init-method方法;
- 調用BeanPostProcessor的postProcessAfterInitialization方法;當進行到這一步,Bean已經被準備就緒了,一直停留在應用的上下文中,直到被銷毀;
- 如果應用的上下文被銷毀了,如果Bean實作了DisposableBean接口,則調用destroy方法,如果Bean定義了destory-method聲明了銷毀方法也會被調用。
基于Java的配置
從這裡出發:
AnnotationConfigApplicationContext context=
new AnnotationConfigApplicationContext(AppConfig.class);
AnnotationConfigApplicationContext的結構關系:
建立AnnotationConfigApplicationContext對象
//根據參數類型可以知道,其實可以傳入多個annotatedClasses,但是這種情況出現的比較少
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//調用無參構造函數,會先調用父類GenericApplicationContext的構造函數
//父類的構造函數裡面就是初始化DefaultListableBeanFactory,并且指派給beanFactory
//本類的構造函數裡面,初始化了一個讀取器:AnnotatedBeanDefinitionReader read,一個掃描器ClassPathBeanDefinitionScanner scanner
//scanner的用處不是很大,它僅僅是在我們外部手動調用 .scan 等方法才有用,正常方式是不會用到scanner對象的
this();
//把傳入的類進行注冊,這裡有兩個情況,
//傳入傳統的配置類
//傳入bean(雖然一般沒有人會這麼做
//看到後面會知道spring把傳統的帶上@Configuration的配置類稱之為FULL配置類,不帶@Configuration的稱之為Lite配置類
//但是我們這裡先把帶上@Configuration的配置類稱之為傳統配置類,不帶的稱之為普通bean
register(annotatedClasses);
//重新整理
refresh();
}
我們先來為構造方法做一個簡單的說明:
- 這是一個有參的構造方法,可以接收多個配置類,不過一般情況下,隻會傳入一個配置類。
- 這個配置類有兩種情況,一種是傳統意義上的帶上@Configuration注解的配置類,還有一種是沒有帶上@Configuration,但是帶有@Component,@Import,@ImportResouce,@Service,@ComponentScan等注解的配置類,在Spring内部把前者稱為Full配置類,把後者稱之為Lite配置類。在本源碼分析中,有些地方也把Lite配置類稱為普通Bean。
使用斷點調試,通過this()調用此類無參的構造方法,代碼到下面:
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
//注解bean定義讀取器,主要作用是用來讀取被注解的了bean
private final AnnotatedBeanDefinitionReader reader;
//掃描器,它僅僅是在我們外部手動調用 .scan 等方法才有用,正常方式是不會用到scanner對象的
private final ClassPathBeanDefinitionScanner scanner;
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
//會隐式調用父類的構造方法,初始化DefaultListableBeanFactory
//初始化一個Bean讀取器
this.reader = new AnnotatedBeanDefinitionReader(this);
//初始化一個掃描器,它僅僅是在我們外部手動調用 .scan 等方法才有用,正常方式是不會用到scanner對象的
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
首先無參構造方法中就是對讀取器
reader
和掃描器
scanner
進行了執行個體化,reader的類型是
AnnotatedBeanDefinitionReader
,可以看出它是一個 “打了注解的Bean定義讀取器”,scanner的類型是
ClassPathBeanDefinitionScanner
,它僅僅是在外面手動調用.scan方法,或者調用參數為String的構造方法,傳入需要掃描的包名才會用到,像這樣方式傳入的配置類是不會用到這個scanner對象的。
AnnotationConfigApplicationContext類是有繼承關系的,會隐式調用父類的構造方法:
下面代碼,初始化DefaultListableBeanFactory
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
@Nullable
private ResourceLoader resourceLoader;
private boolean customClassLoader = false;
private final AtomicBoolean refreshed = new AtomicBoolean();
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
}
DefaultListableBeanFactory的關系圖
DefaultListableBeanFactory是相當重要的,從字面意思就可以看出它是一個Bean的工廠,什麼是Bean的工廠?當然就是用來生産和獲得Bean的。
讓我們把目光回到AnnotationConfigApplicationContext的無參構造方法,讓我們看看Spring在初始化AnnotatedBeanDefinitionReader的時候做了什麼:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
這裡的BeanDefinitionRegistry當然就是AnnotationConfigApplicationContext的執行個體了,這裡又直接調用了此類其他的構造方法:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
讓我們把目光移動到這個方法的最後一行,進入registerAnnotationConfigProcessors方法:
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null);
}
這又是一個門面方法,再點進去,這個方法的傳回值Set,但是上遊方法并沒有去接收這個傳回值,是以這個方法的傳回值也不是很重要了,當然方法内部給這個傳回值指派也不重要了。由于這個方法内容比較多,這裡就把最核心的貼出來,這個方法的核心就是注冊Spring内置的多個Bean:
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
- 判斷容器中是否已經存在了
BeanConfigurationClassPostProcessor
- 如果不存在(當然這裡肯定是不存在的),就通過RootBeanDefinition的構造方法獲得
的ConfigurationClassPostProcessor
,BeanDefinition
是RootBeanDefinition
的子類:BeanDefinition
- 執行registerPostProcessor方法,registerPostProcessor方法内部就是注冊Bean,當然這裡注冊其他Bean也是一樣的流程。
BeanDefinition是什麼?
BeanDefinition聯系圖
它是用來描述Bean的,裡面存放着關于Bean的一系列資訊,比如Bean的作用域,Bean所對應的Class,是否懶加載,是否Primary等等,這個BeanDefinition也相當重要,我們以後會常常和它打交道。**
registerPostProcessor方法:
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
這方法為BeanDefinition設定了一個Role,ROLE_INFRASTRUCTURE代表這是spring内部的,并非使用者定義的,然後又調用了registerBeanDefinition方法,再點進去,Oh No,你會發現它是一個接口,沒辦法直接點進去了,首先要知道registry實作類是什麼,那麼它的實作是什麼呢?答案是DefaultListableBeanFactory:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
這又是一個門面方法,再點進去,核心在于下面兩行代碼:
//beanDefinitionMap是Map<String, BeanDefinition>,
//這裡就是把beanName作為key,ScopedProxyMode作為value,推到map裡面
this.beanDefinitionMap.put(beanName, beanDefinition);
//beanDefinitionNames就是一個List<String>,這裡就是把beanName放到List中去
this.beanDefinitionNames.add(beanName);
從這裡可以看出DefaultListableBeanFactory就是我們所說的容器了,裡面放着beanDefinitionMap,beanDefinitionNames,beanDefinitionMap是一個hashMap,beanName作為Key,beanDefinition作為Value,beanDefinitionNames是一個集合,裡面存放了beanName。打個斷點,第一次運作到這裡,監視這兩個變量:
DefaultListableBeanFactory中的beanDefinitionMap,beanDefinitionNames也是相當重要的,以後會經常看到它,最好看到它,第一時間就可以反應出它裡面放了什麼資料
這裡僅僅是注冊,可以簡單的了解為把一些原料放入工廠,工廠還沒有真正的去生産。
上面已經介紹過,這裡會一連串注冊好幾個Bean,在這其中最重要的一個Bean(沒有之一)就是BeanDefinitionRegistryPostProcessor Bean。
ConfigurationClassPostProcessor實作BeanDefinitionRegistryPostProcessor接口,BeanDefinitionRegistryPostProcessor接口又擴充了BeanFactoryPostProcessor接口,BeanFactoryPostProcessor是Spring的擴充點之一,ConfigurationClassPostProcessor是Spring極為重要的一個類,必須牢牢的記住上面所說的這個類和它的繼承關系。
除了注冊了ConfigurationClassPostProcessor,還注冊了其他Bean,其他Bean也都實作了其他接口,比如BeanPostProcessor等。
BeanPostProcessor接口也是Spring的擴充點之一。
至此,執行個體化AnnotatedBeanDefinitionReader reader分析完畢。
由于正常使用方式是不會用到AnnotationConfigApplicationContext裡面的scanner的,是以這裡就不看scanner是如何被執行個體化的了。
把目光回到最開始,再分析第二行代碼:
register(annotatedClasses);
這裡傳進去的是一個數組,最終會循環調用如下方法:
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//AnnotatedGenericBeanDefinition可以了解為一種資料結構,是用來描述Bean的,這裡的作用就是把傳入的标記了注解的類
//轉為AnnotatedGenericBeanDefinition資料結構,裡面有一個getMetadata方法,可以拿到類上的注解
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//判斷是否需要跳過注解,spring中有一個@Condition注解,當不滿足條件,這個bean就不會被解析
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//解析bean的作用域,如果沒有設定的話,預設為單例
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//獲得beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解為Lazy,Primary,DependsOn,Role,Description
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//限定符處理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理論上是任何注解,這裡沒有判斷注解的有效性),如果我們在外面,以類似這種
//AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);正常方式去初始化spring,
//qualifiers永遠都是空的,包括上面的name和instanceSupplier都是同樣的道理
//但是spring提供了其他方式去注冊bean,就可能會傳入了
if (qualifiers != null) {
//可以傳入qualifier數組,是以需要循環處理
for (Class<? extends Annotation> qualifier : qualifiers) {
//Primary注解優先
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//Lazy注解
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
//其他,AnnotatedGenericBeanDefinition有個Map<String,AutowireCandidateQualifier>屬性,直接push進去
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//這個方法用處不大,就是把AnnotatedGenericBeanDefinition資料結構和beanName封裝到一個對象中
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注冊,最終會調用DefaultListableBeanFactory中的registerBeanDefinition方法去注冊,
//DefaultListableBeanFactory維護着一系列資訊,比如beanDefinitionNames,beanDefinitionMap
//beanDefinitionNames是一個List<String>,用來儲存beanName
//beanDefinitionMap是一個Map,用來儲存beanName和beanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
在這裡又要說明下,以正常方式去注冊配置類,此方法中除了第一個參數,其他參數都是預設值。
- 通過AnnotatedGenericBeanDefinition的構造方法,獲得配置類的BeanDefinition,這裡是不是似曾相似,在注冊ConfigurationClassPostProcessor類的時候,也是通過構造方法去獲得BeanDefinition的,隻不過當時是通過RootBeanDefinition去獲得,現在是通過AnnotatedGenericBeanDefinition去獲得。
- 判斷需不需要跳過注冊,Spring中有一個@Condition注解,如果不滿足條件,就會跳過這個類的注冊。
- 然後是解析作用域,如果沒有設定的話,預設為單例。
- 獲得BeanName。
- 解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解為Lazy,Primary,DependsOn,Role,Description。
- 限定符處理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理論上是任何注解,這裡沒有判斷注解的有效性)。
- 把AnnotatedGenericBeanDefinition資料結構和beanName封裝到一個對象中(這個不是很重要,可以簡單的了解為友善傳參)。
- 注冊,最終會調用DefaultListableBeanFactory中的registerBeanDefinition方法去注冊:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
//擷取beanName
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
//注冊bean
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//Spring支援别名
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
這個registerBeanDefinition是不是又有一種似曾相似的感覺,沒錯,在上面注冊Spring内置的Bean的時候,已經解析過這個方法了,這裡就不重複了,此時,讓我們再觀察下beanDefinitionMap beanDefinitionNames兩個變量,除了Spring内置的Bean,還有我們傳進來的Bean,這裡的Bean當然就是我們的配置類了:
到這裡注冊配置類也分析完畢了。
大家可以看到其實到這裡,Spring還沒有進行掃描,隻是執行個體化了一個工廠,注冊了一些内置的Bean和我們傳進去的配置類,真正的大頭是在第三行代碼:
refresh();
為了驗證上面的邏輯,可以做個試驗:
首先定義了一個Bean,裡面有各種回調和鈎子,其中需要注意下,我在SpringBean的構造方法中列印了studentService,看SpringBean被new的出來的時候,studentService是否被注入了;又在setBeanName中列印了studentService,看此時studentService是否被注入了,以此來驗證,Bean是何時完成的自動注入的(這個StudentServiceImpl 類的代碼就不貼出來了,無非就是一個最普通的Bean):
public class SpringBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, BeanClassLoaderAware {
public SpringBean() {
System.out.println("SpringBean構造方法:" + studentService);
System.out.println("SpringBean構造方法");
}
@Autowired
StudentServiceImpl studentService;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("setBeanClassLoader");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory");
}
@Override
public void setBeanName(String name) {
System.out.println("setBeanName:" + studentService);
System.out.println("setBeanName");
}
public void initMethod() {
System.out.println("initMethod");
}
public void destroyMethod() {
System.out.println("destroyMethod");
}
}
再定義一個BeanPostProcessor,在重寫的兩個方法中進行了判斷,如果傳進來的beanName是springBean才進行列印:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("springBean")) {
System.out.println("postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("springBean")) {
System.out.println("postProcessAfterInitialization");
}
return bean;
}
}
定義一個配置類,完成自動掃描,但是SpringBean是手動注冊的,并且聲明了initMethod和destroyMethod:
@Configuration
@ComponentScan
public class AppConfig {
@Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
public SpringBean springBean() {
return new SpringBean();
}
}
最後就是啟動類了:
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext(AppConfig.class);
annotationConfigApplicationContext.destroy();
}
運作結果:
SpringBean構造方法:null
SpringBean構造方法
setBeanName:com.codebear.StudentServiceImpl@31190526
setBeanName
setBeanClassLoader
setBeanFactory
postProcessBeforeInitialization
afterPropertiesSet
initMethod
postProcessAfterInitialization
destroy
destroyMethod
可以看到,試驗結果和上面分析的完全一緻。
這就是廣為流傳的Spring生命周期。
也許你在應付面試的時候,是死記硬背這些結論的,現在我帶着你找到這些方法,跟我來。
首先我們來到AnnotationConfigApplicationContext的構造方法:
//根據參數類型可以知道,其實可以傳入多個annotatedClasses,但是這種情況出現的比較少
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//調用無參構造函數,會先調用父類GenericApplicationContext的構造函數
//父類的構造函數裡面就是初始化DefaultListableBeanFactory,并且指派給beanFactory
//本類的構造函數裡面,初始化了一個讀取器:AnnotatedBeanDefinitionReader read,一個掃描器ClassPathBeanDefinitionScanner scanner
//scanner的用處不是很大,它僅僅是在我們外部手動調用 .scan 等方法才有用,正常方式是不會用到scanner對象的
this();
//把傳入的類進行注冊,這裡有兩個情況,
//傳入傳統的配置類
//傳入bean(雖然一般沒有人會這麼做
//看到後面會知道spring把傳統的帶上@Configuration的配置類稱之為FULL配置類,不帶@Configuration的稱之為Lite配置類
//但是我們這裡先把帶上@Configuration的配置類稱之為傳統配置類,不帶的稱之為普通bean
register(annotatedClasses);
//重新整理
refresh();
}
進入refresh方法,refresh方法中有一個finishBeanFactoryInitialization小方法,這個方法是用來執行個體化懶加載單例Bean的,也就是我們的Bean都是在這裡被建立出來的(當然我這裡說的的是絕大部分情況是這樣的):
finishBeanFactoryInitialization(beanFactory);
我們再進入finishBeanFactoryInitialization這方法,裡面有一個beanFactory.preInstantiateSingletons()方法:
//初始化所有的非懶加載單例
beanFactory.preInstantiateSingletons();
我們嘗試再點進去,這個時候你會發現這是一個接口,好在它隻有一個實作類,是以可以我們來到了他的唯一實作,實作類就是org.springframework.beans.factory.support.DefaultListableBeanFactory,這裡面是一個循環,我們的Bean就是循環被建立出來的,我們找到其中的getBean方法:
getBean(beanName);
這裡有一個分支,如果Bean是FactoryBean,如何如何,如果Bean不是FactoryBean如何如何,好在不管是不是FactoryBean,最終還是會調用getBean方法,是以我們可以毫不猶豫的點進去,點進去之後,你會發現,這是一個門面方法,直接調用了doGetBean方法:
return doGetBean(name, null, null, false);
再進去,不斷的深入,接近我們要尋找的東西。
這裡面的比較複雜,但是有我在,我可以直接告訴你,下一步我們要進入哪裡,我們要進入
if (mbd.isSingleton()) {
//getSingleton中的第二個參數類型是ObjectFactory<?>,是一個函數式接口,不會立刻執行,而是在
//getSingleton方法中,調用ObjectFactory的getObject,才會執行createBean
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
這裡面的createBean方法,再點進去啊,但是又點不進去了,這是接口啊,但是别慌,這個接口又隻有一個實作類,是以說 沒事,就是幹,這個實作類為org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。
這個實作的方法裡面又做了很多事情,我們就不去看了,我就是帶着大家找到那幾個生命周期的回調到底定義在哪裡就OK了。
Object beanInstance = doCreateBean(beanName, mbdToUse, args);//建立bean,核心
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
再繼續深入doCreateBean方法,這個方法又做了一堆一堆的事情,但是值得開心的事情就是 我們已經找到了我們要尋找的東西了。
建立執行個體
首先是建立執行個體,位于:
instanceWrapper = createBeanInstance(beanName, mbd, args);//建立bean的執行個體。核心
填充屬性
其次是填充屬性,位于:
populateBean(beanName, mbd, instanceWrapper);//填充屬性,炒雞重要
在填充屬性下面有一行代碼:
exposedObject = initializeBean(beanName, exposedObject, mbd);
繼續深入進去。
aware系列接口的回調
aware系列接口的回調位于initializeBean中的invokeAwareMethods方法:
invokeAwareMethods(beanName, bean);
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
BeanPostProcessor的postProcessBeforeInitialization方法
BeanPostProcessor的postProcessBeforeInitialization方法位于initializeBean的
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
afterPropertiesSet init-method
afterPropertiesSet init-method位于initializeBean中的
invokeInitMethods(beanName, wrappedBean, mbd);
這裡面調用了兩個方法,一個是afterPropertiesSet方法,一個是init-method方法:
((InitializingBean) bean).afterPropertiesSet();
invokeCustomInitMethod(beanName, bean, mbd);
BeanPostProcessor的postProcessAfterInitialization方法
BeanPostProcessor的postProcessAfterInitialization方法位于initializeBean的
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
當然在實際的開發中,應該沒人會去銷毀Spring的應用上下文把,是以剩餘的兩個銷毀的回調就不去找了。
這就是廣為流傳的Spring Bean的生命周期,我也帶着大家找到了各種回調和鈎子,但是我認為這并非是Spring Bean完整的生命周期,隻是經過簡化的,那麼我認為的完整的生命周期是如何的呢,請聽下回分解。