Spring IoC Container 基礎

what is Spring IoC

spring 是一個實現IoC原理的容器。spring容器中的對象通過constructor 參數,Factory method 參數或者Properties來描述它的依賴。當spring創建對象的時候,由spring來注入它的依賴,而不是由對象本身來控制依賴對象的創建,這也是IoC名字的由來。

Configuration Metadata

spring如何創建一個對象呢,你當然得告訴它如何去創建它。有三種方式來告訴spring如何創建對象。

1. xml

2. annotation-based configuration

3. java based configuration

主要通過@Configuration和@Bean
第二種和第三種可以歸結為一種,本質上都是基於annotaton的方式,第三種的方式對bean沒有侵入,不需要在bean上來聲明註解。

Bean lifecycle

對象的創建由spring來負責,spring提供了許多callback和Aware接口來參與對象的創建過程。

1. InitializingBean

2. DisposableBean

3. ApplicationAware

Container extension point

1. BeanFactoryPostProcessor,定製Configuration Metadata

2. BeanPostProcessor, 定製bean的實例

3. FactoryBean, 定製對象的創建

BeanFactoryPostProcessor的應用

先看一下接口的定義。

<code>@FunctionalInterface
public interface BeanFactoryPostProcessor {

\tvoid postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}/<code>

該接口可用來修改application context中內部維護的BeanFactory。當該接口被調用時, 所有的bean definition都已經被加載到BeanFacotry當中, 但是bean還沒有實例化。這個接口提供了機會來修改bean definition,我們可以利用這個擴展機制來改寫bean definition。

PropertySourcesPlaceholderConfigurer 就是利用了這個特性來解析(覆寫)bean definition 屬性值之中的${...}佔位符。

BeanPostProcessor的應用

先看一下interface定義

<code>public interface BeanPostProcessor {

\t@Nullable
\tdefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
\t\treturn bean;
\t}

\t@Nullable
\tdefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
\t\treturn bean;
\t}
/<code>

當該callback被調用時,對象及其依賴的對象已經被創建。postProcessBeforeInitialization在對象的初始化方法前被調用,postProcessAfterInitialization在對象的初始化之後被調用。這個接口的實現者可以定製化bean的實例,例如校驗是否實現接口, 包裝該bean生成一個代理。當校驗是否實現某些接口時, 一般在postProcessBeforeInitialization中做, 當包裝原始bean生成一個代理時, 一般在postProcessAfterInitialization中做,這樣的話原始bean已經完成了初始化。

FactoryBean的應用

<code>public interface FactoryBean {

\tT getObject() throws Exception;

\tClass> getObjectType();

\tdefault boolean isSingleton() {
\t\treturn true;
\t}

}
/<code>

從接口的定義中我們可以看到FactoryBean就是對象的創建工廠。如果一個對象的創建邏輯非常複雜,我們就可以實現這個接口來把複雜的邏輯封裝起來。如果一個bean實現了這個接口,它被作為一個要暴露的對象的工廠,而不是該bean本身被暴露出來。當從BeanFactory中獲取該對象時,不是該對象被返回,而是返回由它創建的對象。 spring框架本身就大量利用了這個特性。如JndiObjectFactoryBean, 它封裝瞭如何從jndi上獲取對象的邏輯。

How Java-based configurations works internally

所有的@Configuration類在Spring啟動的時候都會利用CGLIB生成一個子類,該子類會覆寫@Bean方法,它會首先檢查spring容器中是否已經存在要請求的Bean, 如果不存在,則調用父類的方法來創建bean。 當以@Bean方式來註冊BeanPostProcessor和BeanFactoryPostProcessor時, @Bean方法要聲明成static,避免@Configuration類的提前加載。


分享到:


相關文章: