碼雲地址帶有上篇文章中所用的中文註釋和測試類,分支my-test
Spring 是漸進式的工具,並不具有很強的侵入性,它的模塊也劃分得很合理,即使你的應用不是 web 應用,或者之前完全沒有使用到 Spring,而你就想用 Spring 的依賴注入這個功能,其實完全是可以的,它的引入不會對其他的組件產生衝突
ApplicationContext繼承結構
構建 ApplicationContext的方案有很多,先來看看大體的繼承結構是怎麼樣的:
我們可以使用 FileSystemXmlApplicationContext 和 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 這三個類來構建 ApplicationContext
1、FileSystemXmlApplicationContext 的構造函數需要一個 xml 配置文件在系統中的路徑,和 ClassPathXmlApplicationContext 基本上一樣。
2、ClassPathXmlApplicationContext 是根據 xml 文件內容來構建 ApplicationContext,就是在 ClassPath 中尋找 xml 配置文件。
3、AnnotationConfigApplicationContext 是基於註解來使用的,它不需要配置文件,採用 java 配置類和各種註解來配置,目前主流方式。
BeanFactory繼承結構
ApplicationContext 其實就是一個 BeanFactory,生產 bean 的工廠,它負責生產和管理各個 bean 實例,繼承結構:
-
ApplicationContext 繼承了 ListableBeanFactory,這個 Listable 的意思就是,通過這個接口,我們可以獲取多個 Bean,大家看源碼會發現,最頂層 BeanFactory 接口的方法都是獲取單個 Bean 的。
-
ApplicationContext 繼承了 HierarchicalBeanFactory,Hierarchical 單詞本身已經能說明問題了,也就是說我們可以在應用中起多個 BeanFactory,然後可以將各個 BeanFactory 設置爲父子關係。
-
AutowireCapableBeanFactory 用來自動裝配 Bean 用的,但是仔細看上圖,ApplicationContext 並沒有繼承它,不過不用擔心,不使用繼承,不代表不可以使用組合,如果你看到 ApplicationContext 接口定義中的最後一個方法 getAutowireCapableBeanFactory() 就知道了。
-
ConfigurableListableBeanFactory 也是一個特殊的接口,看圖,特殊之處在於它繼承了第二層所有的三個接口,而 ApplicationContext 沒有。這點之後會用到。
BeanFactory、ListableBeanFactory、HierarchicalBeanFactory、AutowireCapableBeanFactory、ApplicationContext 這幾個接口中的方法:
啓動過程分析
public class Test {
public static void main(String[] args) {
// 實例化ApplicationContext容器對象
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Appconfig.class);
context.getBean(Z.class);
}
}
通過創建AnnotationConfigApplicationContext對象,執行構造方法裏的refresh()方法(初始化容器),爲什麼是 refresh(),而不是 init() 這種名字的方法。因爲 ApplicationContext 建立起來以後,其實我們是可以通過調用 refresh() 這個方法重建的,refresh() 會將原來的 ApplicationContext 銷燬,然後再重新執行一次初始化操作
refresh() 方法裏面調用的方法很多,一個一個方法來看大概做了些什麼事情,首先是prepareRefresh()
prepareRefresh
這個方法主要是記錄啓動時間,校驗 xml 配置文件,檢驗environment的properties是否正確,initPropertySources會調用GenericWebApplicationContext的實現,設置容器的環境,初始化容器的屬性
obtainFreshBeanFactory
因爲上面調用了GenericApplicationContext的實現,觸發構造方法,這裏將會創建 BeanFactory,也就是創建了DefaultListableBeanFactory,如下:
/**
* Create a new GenericApplicationContext.
* @see #registerBeanDefinition
* @see #refresh
*/
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
obtainFreshBeanFactory方法其實就是拿到之前創建的 beanFactory 對象,spring容器是通過 ConfigurableListableBeanFactory 這個bean工廠進行真正的bean加載。其主要做了三個動作,刷新 beanFactory,獲取 beanFactory,返回 beanFactory
/**
* Tell the subclass to refresh the internal bean factory
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新 BeanFactory並指定序列化id
// 調用了AtomicBoolean的compareAndSet方法,保證只刷新一次
// 如果再次調用refresh()方法,則會拋出異常
refreshBeanFactory();
// 返回剛剛創建的 BeanFactory
return getBeanFactory();
}
這步完成後,配置文件就會解析成一個個 Bean 定義,註冊到 BeanFactory 中,註冊也只是將這些信息都保存到了註冊中心(說到底核心是一個 beanName-> beanDefinition 的 map),這裏說的 Bean 還沒有初始化,只是配置信息都提取出來了
prepareBeanFactory
在註冊bean之前先給beanFactory配置一些屬性,它們可以幫助beanFactory後期去解析、註冊其他的bean
如果上述幾個Aware不使用ignoreDependencyInterface會有什麼問題呢?如果我們寫一個實現類,然後給他默認配置ApplicationContext屬性,而這個ApplicationContext是我們自己new的,這就導致了我們使用的不是spring自己生成的ApplicationContext,所以spring爲了避免我們手誤自己註冊下這個屬性,而幫我們忽略。
registerResolvableDependency就是當我們使用自動注入比如@AutoWired注入BeanFactory 類型時,他會幫我們注入目前輸入的實例對象,而不會去注入他的其他實現類,這是爲了避免我們使用其他的自定義的實例對象
postProcessBeanFactory
Spring中並沒有具體去實現postProcessBeanFactory方法,是提供給想要實現BeanPostProcessor的三方框架使用的。誰要使用誰就去實現。其實就是向上下文中添加了一系列的Bean的後置處理器,後置處理器工作的時機是在所有的beanDefinition加載完成之後,bean實例化之前執行。簡單來說Bean的後置處理器是用來修改BeanDefinition的屬性信息的
invokeBeanFactoryPostProcessors
實例化和調用所有 BeanFactoryPostProcessor(包括其子類 BeanDefinitionRegistryPostProcessor),在該方法中完成IoC容器的初始化;代碼較多,推薦閱讀此篇文章
此方法執行完成後,我們自己創建加了註解的Bean會被put到beanDefinitionMap中,上篇文章中有講
registerBeanPostProcessors
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 獲取所有實現BeanPostProcessor接口的bean的名稱
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
// 加一是因爲方法末尾會註冊一個ApplicationListenerDetector接口的實現類
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
// 註冊 BeanPostProcessorChecker,用於每個bean的初始化完成後,做一些簡單的檢查
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 緩存實現了priorityOrdered接口的bean
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
// 排序、註冊
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
// 緩存實現Ordered接口的bean
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 排序、註冊
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
// 緩存沒有實現兩個接口的bean
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 註冊
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
// 排序註冊所有的實現了MergedBeanDefinitionPostProcessor接口的bean
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// 註冊ApplicationListenerDetector,用來檢查所有的ApplicationListener
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
這裏只是註冊,相當於整理所有的BeanPostProcessor,把其提出來,按執行循序放到list中,供後續調用。原來我們只知道所有的BeanPostProcessor都在IoC容器中以bean的形式存在着,但是我們不知道應該如何去執行,以什麼順序去執行。經過該方法解決了該問題
最後幾個方法
// Initialize message source for this context.
// 初始化當前 ApplicationContext 的 MessageSource,主要做國際化處理
initMessageSource();
// Initialize event multicaster for this context.
// 初始化當前 ApplicationContext 的事件廣播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 具體的子類可以在這裏初始化一些特殊的 Bean(在初始化 singleton beans 之前)
// 空殼方法,類似postProcessBeanFactory()
onRefresh();
// Check for listener beans and register them.
// 註冊事件監聽器,監聽器需要實現 ApplicationListener 接口
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化所有的 singleton beans,上篇文章已分析
//(lazy-init 的除外)
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 最後,廣播事件,ApplicationContext 初始化完成
finishRefresh();
// Destroy already created singletons to avoid dangling resources.
// 銷燬已經初始化的 singleton 的 Beans,以免有些 bean 會一直佔用資源
destroyBeans();
// Reset 'active' flag.
// 設置active表示爲false
cancelRefresh(ex);
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
// 清除反射的緩存
// 清除註解的相關緩存
// 清除classloader緩存
resetCommonCaches();