spring原始碼學習筆記-初始化(三)-BeanFactory
轉自http://www.sandzhang.com/blog/2011/04/05/spring-study-notes-initialization-3/
refresh()方法中在上篇obtainFreshBeanFactory()方法建立了beanfactory物件,之後的程式碼就開始是對beanFactory物件的一些處理,BeanFactory相關的一些內容也是spring的核心內容。
注:refresh()的程式碼就不再次列舉了,請看spring原始碼中AbstractApplicationContext類。
一、首先是prepareBeanFactory(beanFactory),主要是做了一些beanFactory的初始化工作,因為這個方法比較長,我們分成4部分來看,
第1部分程式碼:
[java] view plaincopyprint?- beanFactory.setBeanClassLoader(getClassLoader());
- beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
- beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
- beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(
- beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
- beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
- beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
- beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
- beanFactory.registerResolvableDependency(BeanFactory.
- beanFactory.registerResolvableDependency(ResourceLoader.class, this);
- beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
- beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
- 第1行設定beanFactory的classLoader為當前context的classLoader
- 第2行設定beanFactory的表示式語言處理器,spring3增加了表示式語言的支援,預設可以使用#{bean.xxx}的形式來呼叫相關屬性值。
- 第3行為beanFactory增加了一個預設的propertyEditor,這個主要是對bean的屬性等設定管理的一個工具,以後再做詳細分析。
- 第4行添加了一個處理aware相關介面的beanPostProcessor擴充套件,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置處理方法實現aware相關介面的功能,aware介面是用來給bean注入一些資源的介面,例如實現BeanFactoryAware的Bean在初始化後,Spring容器將會注入BeanFactory的例項相應的還有ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等。
- 第5-8行設定了幾個忽略自動裝配的介面,預設只有BeanFactoryAware被忽略,其他的都要自行設定,這裡設定了ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware和ApplicationContextAware。
- 第9-12行設定了幾個自動裝配的特殊規則,如果是BeanFactory型別,則注入beanFactory物件,如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext型別則注入當前物件(applicationContext物件)。
第2部分程式碼:
- if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
- beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
- beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
- }
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
- 這部分判斷是否定義了名為loadTimeWeaver的bean,如果定義了則新增loadTimeWeaver功能的beanPostProcessor擴充套件,並且建立一個臨時的classLoader來讓其處理真正的bean。spring的loadTimeWeaver主要是通過 instrumentation 的動態位元組碼增強在裝載期注入依賴。具體這部分還沒有很好的理解,暫時標記一下以後再專門研究看看。
第3部分程式碼:
[java] view plaincopyprint?- if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
- Map systemProperties;
- try {
- systemProperties = System.getProperties();
- } catch (AccessControlException ex) {
- systemProperties = new ReadOnlySystemAttributesMap() {
- protected String getSystemAttribute(String propertyName) {
- try {
- return System.getProperty(propertyName);
- } catch (AccessControlException ex) {
- if (logger.isInfoEnabled()) {
- logger.info("Not allowed to obtain system property [" + propertyName + "]: " +
- ex.getMessage());
- }
- returnnull;
- }
- }
- };
- }
- beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
- }
if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
Map systemProperties;
try {
systemProperties = System.getProperties();
} catch (AccessControlException ex) {
systemProperties = new ReadOnlySystemAttributesMap() {
protected String getSystemAttribute(String propertyName) {
try {
return System.getProperty(propertyName);
} catch (AccessControlException ex) {
if (logger.isInfoEnabled()) {
logger.info("Not allowed to obtain system property [" + propertyName + "]: " +
ex.getMessage());
}
return null;
}
}
};
}
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
}
這部分首先判斷是否定義了名為systemProperties的bean,如果沒有則載入系統獲取當前系統屬性System.getProperties()並註冊為一個單例bean。假如有AccessControlException許可權異常則建立一個ReadOnlySystemAttributesMap物件,可以看到建立時重寫了getSystemAttribute()方法,檢視ReadOnlySystemAttributesMap的程式碼可以得知在呼叫get方法的時候會去呼叫這個方法來獲取key對應的物件,當獲取依舊有許可權異常AccessControlException的時候則返回null。
第4部分程式碼:
- if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
- Map<String,String> systemEnvironment;
- try {
- systemEnvironment = System.getenv();
- } catch (AccessControlException ex) {
- systemEnvironment = new ReadOnlySystemAttributesMap() {
- protected String getSystemAttribute(String variableName) {
- try {
- return System.getenv(variableName);
- } catch (AccessControlException ex) {
- if (logger.isInfoEnabled()) {
- logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +
- ex.getMessage());
- }
- returnnull;
- }
- }
- };
- }
- beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
- }
if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
Map<String,String> systemEnvironment;
try {
systemEnvironment = System.getenv();
} catch (AccessControlException ex) {
systemEnvironment = new ReadOnlySystemAttributesMap() {
protected String getSystemAttribute(String variableName) {
try {
return System.getenv(variableName);
} catch (AccessControlException ex) {
if (logger.isInfoEnabled()) {
logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +
ex.getMessage());
}
return null;
}
}
};
}
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
}
- 這部分和上面一部分類似,只不過由系統屬性改為了系統環境變數,異常處理方式等也和上面一部分一樣。這兩部分都是為spring內部提供系統資訊的支撐bean。
二、prepareBeanFactory()方法呼叫之後,是一個try-catch程式碼塊,如果有BeanException異常產生則會停止refresh並且銷燬已建立的資源,現在看程式碼塊裡的第一行postProcessBeanFactory(beanFactory)
postProcessBeanFactory()方法,預設方法體是空的,主要是用來擴充套件beanfactory的,擴充套件點是在bean等配置都已經載入但還沒有進行例項化的時候。
例如上面說到的aware相關介面自動裝配設定,假如是web專案,使用的是spring的webApplicationcontext,這時需要一些ServletContextAware相關的自動裝配忽略及配置等,就需要在webApplicationContext裡重寫這個方法來實現相應功能。