国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

白話文剖析[spring4.2.1.RELEASE]IOC核心架構

2019-11-14 14:54:20
字體:
來源:轉載
供稿:網友

在這篇文章中,我將用第一人稱的方式向你闡述sPRing4.2.1.RELEASE IOC部分的基本架構,你可以用如下的簡單demo開啟源碼debug之旅

demo包含三個文件


User.java

public class User {    @Override    public String toString() {        return hi, I am a user!;    }}

user.xml

    

UserTest.java

public class UserTest {    public static void main(String[] args) {        applicationContext context = new ClassPathXmlApplicationContext(ch0/user.xml);        User user = context.getBean(User.class);        System.out.println(user);    }}

UserTest.java 中通過ClassPathXmlApplicationContext 創建了一個上下文,xml文件在類路徑下,然后通過getBean 的方式可以拿到該bean

我們直接進到new ClassPathXmlApplicationContext(“ch0/user.xml”); 看看我到底做了什么事情~_~

ClassPathXmlApplicationContext.java

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {        this(new String[] {configLocation}, true, null);}

調用

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)            throws BeansException {        // 層層調用父類構造函數, 最終只是為了獲取ResourcePatternResolver, 我需要這玩意是因為我        // 要將你傳給我的配置文件(ch0/user.xml)這個參數轉換為我內部可以處理的資源抽象 Resource         super(parent);        // 你可以不用告訴我非常精確的配置文件, 可以寫占位符。在這個函數里面,我可以解析出完整的配置文件路徑        setConfigLocations(configLocations);        // 基本都需要刷新的啦(refresh == true),在刷新上下文的時候,我會用你給我的配置文件完成幾乎所有的事情哦        if (refresh) {            refresh();        }}

上面的函數先調用super(parent) 層層往上調用,最終發現做了這么一件事情

AbstractApplicationContext.java

public AbstractApplicationContext() {        this.resourcePatternResolver = getResourcePatternResolver();}

resourcePatternResolver 這從字面上就可以知道這家伙是做資源解析的用的呢,查看一下ResourcePatternResolver 的定義,發現重點只有這么一行

ResourcePatternResolver.java

    Resource[] getResources(String locationPattern) throws IOException;

這里的 locationPattern 代表實際的資源路徑(基本上就等同于xml文件路徑啦),這家伙可以把一個資源路徑轉換為描述資源的抽象Resource, 好了,初次看spring源碼了解到這里就夠了,關于 Resource的深入里面后面會后專題分析!

繼續下面一行

setConfigLocations(configLocations);

public void setConfigLocations(String... locations) {        if (locations != null) {            Assert.noNullElements(locations, Config locations must not be null);            this.configLocations = new String[locations.length];            for (int i = 0; i < locations.length; i++) {                this.configLocations[i] = resolvePath(locations[i]).trim();            }        }        else {            this.configLocations = null;        }}

這一句的作用就是將創建ApplicationContext傳入進來的ch0/user.xml 轉換為合法的location,將location里面類似${key} 的placeHolder 轉換為實際的值

protected String resolvePath(String path) {        return getEnvironment().resolveRequiredPlaceholders(path);}

而轉換過程中會通過getEnviroment()拿到ConfigurableEnvironment對象來進行占位符${}的替換,標準的Enviroment對象為

StandardEnvironment.java

public class StandardEnvironment extends AbstractEnvironment {    public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = systemEnvironment;    public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = systemProperties;    @Override    protected void customizePropertySources(MutablePropertySources propertySources) {        propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));        propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));    }}

可以看到在設置替換placeHolder的源的時候,最終會通過getProperties(),和System.getenv()來獲取啟動jvm的時候的環境變量和系統環境變量,也就是說,如果你傳入的location里面有個${key} 占位,而jvm參數或者系統環境變量里面剛好有個變量叫做key 那么spring在解析該location的時候,會將該占位解析為對應的value


接下來,到了

if (refresh) {    refresh();}

這一行可是我的重頭戲啊,我的核心功能都在這個refresh() 方法里面搞定哦
在我們這個demo中,refresh 參數為true,所以,直接進入到refresh()方法,激動人心的時刻終于到來,go!

AbstractApplicationContext.java

public void refresh() throws BeansException, IllegalStateException {        synchronized (this.startupShutdownMonitor) {            // 刷新工廠之前需要做一些準備工作的啦,就想你在運動之前要做一些準備運動一樣哦             prepareRefresh();            // 我會告訴我的子類創造一個工廠,來把我需要創建bean的原料BeanDefinition準備好            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();            // 原料準備好之后呢,我要聲明一些特殊的依賴關系, 所謂依賴,就是我在創造一個bean A的時候,發現它里面有另外一個屬性B            // 那么B就是A的依賴,我在創造A的時候,必須先把B創造好,特殊關系的依賴就是指我遇到B的類型,我該放棄呢,還是告訴他直接用            // 現成的(也就是不用再去創造B了)            prepareBeanFactory(beanFactory);            try {                // 這里沒啥,就是留給子類做擴展的啦                postProcessBeanFactory(beanFactory);                // 到了這里,工廠已經準備好了,如果你之前告訴過我工廠準備好之后應該干什么事情,這邊我就可以滿足你的需求哦                // 不信,你去看看BeanFactoryPostProcessors接口是干嘛用的吧==                invokeBeanFactoryPostProcessors(beanFactory);                // 在創建一個bean的前后,我也留給你很多擴展,原理上和上面的工廠擴展差不多的哦                registerBeanPostProcessors(beanFactory);                // 就是處理一些國際化的操作啦,啊?什么是國際化,就是i18n啦,還不懂?你沒救了                initMessageSource();                // 我的功能很豐富,除了可以給你創建bean,還可以有事件管理的功能哦,這里我就創建一個管理器(ApplicationEventMulticaster(),                // 用來注冊事件(ApplicationEvent)                // 我會將這些事件廣播給合適的監聽者(ApplicationListener)那邊哦                initApplicationEventMulticaster();                // 啥也不干,留給子類擴展啦                onRefresh();                // 前面不是事件管理器搞好了嘛,這邊呢,就是把那些事件監聽器給注冊進來啦,這樣來一個新的事件我就知道該發給誰啦                registerListeners();                // 如果某些bean告我我,他想在我工廠創建之初就想初始化(一般要是單件singleton并且lazy-init為false),那么我在這個函數會滿足他                finishBeanFactoryInitialization(beanFactory);                // 終于刷新完了,我要開始發布事件了!                finishRefresh();            }            // 什么?刷新的時候報錯了?oh my god,我需要做一些清理            catch (BeansException ex) {                logger.warn(Exception encountered during context initialization - cancelling refresh attempt, ex);                // 我需要將我創建的bean銷毀掉                destroyBeans();                // 我不再活躍                cancelRefresh(ex);                // 我要告訴你,我出異常了,救我!!                throw ex;            }            finally {                // 一些通用的緩存清掉!!                resetCommonCaches();            }        }    }

下面, 我來告訴你每個函數我到底做了哪些見不得人的事==, ready?go!!

prepareRefresh();

protected void prepareRefresh() {        this.startupDate = System.currentTimeMillis();        this.active.set(true);        if (logger.isInfoEnabled()) {            logger.info(Refreshing  + this);        }        // 初始化占位符placeHolder源頭        initPropertySources();        // 驗證一些必要屬性, 當然這些必要屬性是你告訴我的哦        getEnvironment().validateRequiredProperties();        // 誒呀,我在刷新的時候事件管理器還沒做好呢,我得先創建一個臨時的池子,好讓在沒創建事件管理器之前將需要發布的事件存起來啊!        this.earlyApplicationEvents = new LinkedHashSet();}

好的,到了這里我要開始刷新整個ApplicationContext了。

首先,我會記錄下刷新時間,將ApplicationContext標志為活躍狀態 然后,我在解析配置文件中的placeHolder的時候,會需要一些資源,所以,我會初始化 PropertySources, 該函數默認為空實現protected,表明是留給子類實現的,比如web里面的上下文什么的 接下來,我要驗證一下我需要的一些必要屬性有沒有設置,如果沒有設置,我是不會讓你繼續下去的,直接拋個MissingRequiredPropertiesException異常給你玩 最后,我將初始化一下我接受事件的載體earlyApplicationEvents,這玩意里面將保存所有的通過AbstractApplicationContext: publishEvent(ApplicationEvent event)來publish的事件

到了這里,我準備刷新的工作做完了,這邊真的開始刷新了哦

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {        // 刷啊刷        refreshBeanFactory();        // 刷完了,可以出鍋了        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        if (logger.isDebugEnabled()) {            logger.debug(Bean factory for  + getDisplayName() + :  + beanFactory);        }        return beanFactory;    }

我刷新完工廠,然后將工廠返回,跟我走, 看看在refreshBeanFactory()里面做了哪些事情

AbstractRefreshableApplicationContext.java

 protected final void refreshBeanFactory() throws BeansException {        // 什么?我之前創建過工廠?銷毀掉產品,關掉它!        if (hasBeanFactory()) {            destroyBeans();            closeBeanFactory();        }        try {            // 開始創辦工廠!            DefaultListableBeanFactory beanFactory = createBeanFactory();            // 給工廠取個名字唄            beanFactory.setSerializationId(getId());            // 來,給你特殊定制一下            customizeBeanFactory(beanFactory);            // 加載創建產品(bean)需要的原料(beanDefinition)            loadBeanDefinitions(beanFactory);            synchronized (this.beanFactoryMonitor) {                this.beanFactory = beanFactory;            }        }        catch (IOException ex) {            throw new ApplicationContextException(I/O error parsing bean definition source for  + getDisplayName(), ex);        }}
首先,我會檢查一下我之前有木有創建過Bean工廠,如果創建過,那么我要先將ta銷毀,銷毀的意思嘛,就是將我bean工廠里面的所有的單例bean全清除掉哦,然后將工廠關閉,就是把我的bean工廠的名字也抹掉啦 然后,我要開始創建新的bean工廠了,第7行中,我要先把廠子搭建好,這樣,才能容得下之后的bean啊,這里偷偷告訴大家,這里創建出來的DefaultListableBeanFactory可是重量級嘉賓,你用到的許許多多的bean什么的都是這家伙搞出來的呢 接下來呢,我就給工廠取個好聽的名字,然后將你告訴我的兩樣重要的事情轉達給bean工廠
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {        if (this.allowBeanDefinitionOverriding != null) {            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);        }        if (this.allowCircularReferences != null) {            beanFactory.setAllowCircularReferences(this.allowCircularReferences);        }    }

這兩件重要的事情就是,該工廠是否可以支持Bean定義的覆蓋,即是否可以在不同的配置文件里面定義兩個相同名字的的bean;是否支持循環引用,循環引用的意思是A依賴B,B依賴C,結果又發現C依賴A,那就說明A產生了循環依賴,我在解決循環依賴這方面可是很牛逼的,以后有時間我會慢慢向你訴說。
4. 最后,我就開始裝載bean原料(BeanDefinition)了,在這里提一下,很重要的哦,我在創建每個bean的時候,會先將所有bean的原料選準備好,包括bean里面所有屬性的描述,構造防范的描述,依賴關系的描述,我都給抽象好,以便之后我創建bean的時候直接拿來用

loadBeanDefinitions(beanFactory);

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {        // 創造一個xml讀取器,為我的工廠讀取配置        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);        // Configure the bean definition reader with this context's        // resource loading environment.        beanDefinitionReader.setEnvironment(this.getEnvironment());        beanDefinitionReader.setResourceLoader(this);        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));        // Allow a subclass to provide custom initialization of the reader,        // then proceed with actually loading the bean definitions.        initBeanDefinitionReader(beanDefinitionReader);        loadBeanDefinitions(beanDefinitionReader);    }

裝載bean原料(BeanDefinition)的時候,我要先創造一個讀取器(BeanDefinitionReader)來幫載入資源(Resource),大多數情況下,我一般用xml讀取器(XmlBeanDefinitionReader)來讀取資源。創建好了資源讀取器之后,給這個資源讀取器設置一些環境啦(Environment),資源加載器啦(ResourceLoader, 為了讓資源讀取器在讀取到import之類引入其他資源的時候可以通過location轉換為Resource),還有讀取xml的一些輔助(EntityResolver),最終會進入到

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {        Resource[] configResources = getConfigResources();        if (configResources != null) {            reader.loadBeanDefinitions(configResources);        }        String[] configLocations = getConfigLocations();        if (configLocations != null) {            reader.loadBeanDefinitions(configLocations);        }    }

reader可以根據Resource來載入bean原料,也可以根據location來載入bean原料(想想為什么,上面我告訴過你的哦),好了,再跟下去估計你要暈了,就到這里了,總結一下,獲取bean 工廠就是先搭一個廠子,然后通過bean原料讀取器將bean原料載入到bean工廠里面,有了這個bean原料,后面我可以做很多很多事情。

我們繼續回到牛逼哄哄的refresh方法,到了下面這一行, 函數體過于龐大,但都是紙老虎,不要怕!

prepareBeanFactory(beanFactory);

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {        // 我需要只要我在創造bean的時候用啥來加載        beanFactory.setBeanClassLoader(getClassLoader());        // 我還有el表達式(#{})的功能哦,這里就詳細說el是啥玩意啦,自己百度哦        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));        // 屬性轉換器注冊中心,用來注冊屬性轉換器,比如'1989-07-30'轉換為Date類型啦,你得告訴我怎么轉換才行呀        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));        // 特殊的bean后置處理器,用來在bean初始化前后做一些手腳,這個ApplicationContextAwareProcessor        // 的主要作用就是給實現了某些特殊接口的bean注入一些特殊的bean        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));        // 忽略的依賴        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);        // 特殊的依賴規則        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);        beanFactory.registerResolvableDependency(ResourceLoader.class, this);        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);        beanFactory.registerResolvableDependency(ApplicationContext.class, this);        // AOP相關的一些東西,可以先不用關注        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));            // Set a temporary ClassLoader for type matching.            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));        }        // 注入環境相關的一些bean        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());        }        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());        }        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());        }    }
設置類加載器,用于之后bean原料的加工制作 設置el表達式(類似#{key})解析器 設置屬性編輯器注冊中心,屬性編輯器這玩意主要用于屬性從一種形式轉換成另外一種形式,比如從
‘2015-11-26 21:29:11’轉換成為一個合法的java.util.Date 類型,我內置了很多屬性編輯器哦 注入Bean后置處理器(BeanPostProcessor), 關于BeanPostProcessor的具體用法后面會具體描述,這里簡單提一下哦,這個BeanPostProcessor在Bean實例化之前之后可以做一些定制化的操作,從字面意思上來看,ApplicationContextAwareProcessor要做的事情就是給實現了與ApplicationContext相關接口的bean注入一下上下文信息,比如環境呀,工廠呀,上下文呀什么的 下面這五行我會告訴bean工廠,你在解決bean的依賴關系的時候,如果碰到了ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware,EnvironmentAware就不要試圖取獲取這些bean啦,直接忽略掉就行了 上面我告訴bean工廠忽略掉一些bean依賴的注入,下面我同樣會告訴bean工廠,你在解決下面幾個依賴的時候,直接把我告訴你的bean拿去用就行啦,這些bean都是與上下文相關的BeanFactoryResourceLoaderApplicationEventPublisher,ApplicationContext, 猜一下,為啥第二個參數中有this?那就說明我(作為ApplicationContext)同時具有這三者的功能啦,是時候告訴你我是誰了!后面幾行也就是注冊了幾個單例,加載環境信息啦,沒啥好說的。好,放大招,看看我是誰啦
ApplicationContext
我又可以發布事件ApplicationEventPublisher, 又可以通過文件路徑解析資源ResourcePatternResolver, 還可以處理國際化MessageSource, 還可以創建bean,獲取beanListableBeanFactory,并且我可以告訴你我的父工廠是誰HierarchicalBeanFactory, 甚至可以告訴你我現在處在什么環境中 EnvironmentCapable,好啦,我是不是很牛逼,算了,低調,低調,哈哈哈

可以看到,我內部的對象管理也是通過注冊bean來實現的哦,和你定義的bean沒啥本質區別啦

暈啊暈,趕緊回憶一下我們到講到哪一行了,快看,還是在refresh方法里面沒出來啊==<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMiBpZD0="postprocessbeanfactorybeanfactory">postProcessBeanFactory(beanFactory);

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}

是的,你沒看錯,這行里面啥都沒,但是,仔細看哦,這個是protected方法,你懂的,我可以留給我的子類來擴展這個方法做一些更牛逼的事情

轉啊轉,轉到下面這一行,這一行告訴你,我的工廠中制作bean的原料(BeanDefinition)準備好了, 準備好之后,我可以給你一個機會更改這些原料,你通過向我注冊BeanFactoryPostProcessor就可以達到你不可告人的秘密, 在這里,你可以做任何事情,甚至將我的工廠炸毀掉也行啊(搞壞所有的原料)

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

好了,還是看看我是怎么調用你給我注冊的這些后置處理器的吧

invokeBeanFactoryPostProcessors(beanFactory);

調用

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());}

繼續轉啊轉轉到這個類

PostProcessorRegistrationDelegate.java

這個類是在2013-8-28,Juergen Hoeller 這家伙重構過的, since spring 4.0,主要處理一些后置處理器相關的復雜的操作,由于函數體過于龐大,這里我就帶你深入到內部去剖析,帶你裝逼帶你飛

首先,我簡要的告訴你這段代碼做了什么事情,看到傳入的beanFactoryPostProcessors參數沒有,所有的beanFactoryPostProcessor中,他們是最先被執行的哦,他們是通過調用

AbstractApplicationContext

public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) {        this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);}

加入到成員變量 beanFactoryPostProcessors, 然后通過

public List getBeanFactoryPostProcessors() {        return this.beanFactoryPostProcessors;}

傳到這里來的

這里的 BeanFactoryPostProcessors 可以分為兩種,一種是非常普通的,一種是BeanDefinitionRegistryPostProcessor, 字面上意思也可以看的出來,這玩意功能更多呀,
主要多了 postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 這么一個方法, 基本上可以猜出來這個方法是給你注冊bean原料(beanDefinition用的哦)
下面的調用比較復雜,我大概和你先講下做了什么事情

首先呢,check一下我這個工廠是否有注冊bean原料的能力(beanFactory instanceof BeanDefinitionRegistry))
如果有的話:
先處理通過addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor)注冊進來的beanFactoryPostProcessors
處理的時候
如果該后置處理器是 BeanDefinitionRegistryPostProcessor, 先調用它的postProcessBeanDefinitionRegistry方法,由于它又是一個BeanFactoryPostProcessor
所以要將它榨干registryPostProcessors.add(registryPostProcessor);, 以便接下來再調用它的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)的功能
如果是普通的beanFactoryPostProcessors, 保留起來, 然后,按照如下優先級依次調用
1. 實現了PriorityOrdered接口(調用之前先排序)
2. 實現了Ordered接口(調用之前先排序)
3. 普通的BeanDefinitionRegistryPostProcessor
最后,再次調用BeanDefinitionRegistryPostProcessor繼承下來的BeanFactoryPostProcessor的功能,以及普通的beanFactoryPostProcessors

如果這個工廠沒有注冊bean原料的能力,那么說明后置處理器中不存在BeanDefinitionRegistryPostProcessor, 就直接將你通過addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor)
注冊進來的beanFactoryPostProcess執行一遍啦

好了,上面是處理通過addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor)注冊進來的beanFactoryPostProcess
以及BeanDefinitionRegistryPostProcessor, 接下來便是處理普通的BeanFactoryPostProcessor
這邊處理流程就比較簡單了,處理順序為
1. 實現了PriorityOrdered接口(調用之前先排序)
2. 實現了Ordered接口(調用之前先排序)
3. 普通的BeanFactoryPostProcessor

下面,我帶著你分析每一行代碼

    public static void invokeBeanFactoryPostProcessors(            ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {        // 用于記錄處理過的beanFactoryPostProcessors,最簡單的防止重復處理的辦法就是處理完扔到這里面然后每次處理之前看看這里面有沒有,有就不處理        Set processedBeans = new HashSet();        // 如果實現了BeanDefinitionRegistry接口, 那就需要處理BeanDefinitionRegistryPostProcessor, 因為BeanDefinitionRegistryPostProcessor        // 主要就是用來注冊BeanDefinitionRegistry的        if (beanFactory instanceof BeanDefinitionRegistry) {            // 強制轉換一下,以便當參數傳給 BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry的方法            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;            // 記錄普通的BeanFactoryPostProcessor            List regularPostProcessors = new LinkedList();            // 記錄處理過的BeanDefinitionRegistryPostProcessor, 主要是為了之后調用它繼承自BeanFactoryPostProcessor的            // postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法,             List registryPostProcessors =                    new LinkedList();            /**             * BeanDefinitionRegistryPostProcessor 在任何常規的postProcessor之前執行             */            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {                    BeanDefinitionRegistryPostProcessor registryPostProcessor =                            (BeanDefinitionRegistryPostProcessor) postProcessor;                    registryPostProcessor.postProcessBeanDefinitionRegistry(registry);                    // 處理完之后要榨干它哦                    registryPostProcessors.add(registryPostProcessor);                }                else {                    regularPostProcessors.add(postProcessor);                }            }            // 獲取用戶通過非api的方式注冊的BeanDefinitionRegistryPostProcessor, 非api的意思就是在xml獲取通過注解的方式            // 向我隱式注冊, 比如你定義一個類實現了BeanDefinitionRegistryPostProcessor接口,并且這個類對應的bean被我管理,我            // 在這里就可以拿到            String[] postProcessorNames =                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);            // 記錄實現了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor            List priorityOrderedPostProcessors = new ArrayList();            for (String ppName : postProcessorNames) {                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {                    priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));                    // 要記錄一下,這個BeanDefinitionRegistryPostProcessor已經被處理完了哦                    processedBeans.add(ppName);                }            }            // 按照getOrder返回的整數從小到大排序,最小的先執行            sortPostProcessors(beanFactory, priorityOrderedPostProcessors);            // 榨取,繼續榨取            registryPostProcessors.addAll(priorityOrderedPostProcessors);            // 好了,終于可以執行了            invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);            // 記錄實現了Ordered接口的BeanDefinitionRegistryPostProcessor            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);            List orderedPostProcessors = new ArrayList();            for (String ppName : postProcessorNames) {                // 處理之前呢,要看下這個BeanDefinitionRegistryPostProcessor之前有木有處理過哦                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {                    orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));                    processedBeans.add(ppName);                }            }            // 按照getOrder返回的整數從小到大排序,最小的先執行            sortPostProcessors(beanFactory, orderedPostProcessors);            // 榨取,繼續榨取            registryPostProcessors.addAll(orderedPostProcessors);            // 好了,終于可以執行了            invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);            // 最后呢,處理常規的BeanDefinitionRegistryPostProcessor            // 等等,這里為毛這么復雜,還有while循環啊!!!請記住BeanDefinitionRegistryPostProcessor可以干些什么事情哦            // 它可以向我注冊bean,萬一某個BeanDefinitionRegistryPostProcessor(假設叫A)向我注冊的bean的是BeanDefinitionRegistryPostProcessor類型的bean呢(假設為B),按照            // 約定,我也必須搞一遍B啊,那玩意搞B的時候,這個B又向我注冊了一個C,按照約定,我必須要再搞一遍C啊,萬一C..            // 所以,這邊就有個循環啦,直到我把所有的BeanDefinitionRegistryPostProcessor搞完,就結束啦            /**這里是為了保證自定義的postProcessBeanDefinationRegistry里面可能注冊beanPostProcessor**/            boolean reiterate = true;            while (reiterate) {                reiterate = false;                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);                for (String ppName : postProcessorNames) {                    // 如果以前處理過就不處理                    if (!processedBeans.contains(ppName)) {                        BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);                        // 榨取哦                        registryPostProcessors.add(pp);                        // 記錄一下我搞過這個家伙                        processedBeans.add(ppName);                        // 搞之                        pp.postProcessBeanDefinitionRegistry(registry);                        // 搞它的時候它又生出來一個,那我就循環搞它生出來的                        reiterate = true;                    }                }            }            // 搞定從BeanDefinitionRegistryPostProcessor搞榨取出來的普通的postProcessBeanFactory方法            invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);            // 搞定BeanFactoryPostProcessor方法            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);        }        else {            // 如果該工廠沒有實現了BeanDefinitionRegistry接口,那就不需要處理BeanDefinitionRegistryPostProcessor            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);        }        // 拿到所有的BeanFactoryPostProcessor        String[] postProcessorNames =                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);        // 用三個List記錄三種不同類型的BeanFactoryPostProcessor的bean或者名字        List priorityOrderedPostProcessors = new ArrayList();        List orderedPostProcessorNames = new ArrayList();        List nonOrderedPostProcessorNames = new ArrayList();        for (String ppName : postProcessorNames) {            if (!processedBeans.contains(ppName)) {                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {                    priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));                } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {                    orderedPostProcessorNames.add(ppName);                } else {                    nonOrderedPostProcessorNames.add(ppName);                }            }        }        // 執行priorityOrderedPostProcessors之前先排序         sortPostProcessors(beanFactory, priorityOrderedPostProcessors);        // 執行priorityOrderedPostProcessors        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);        // 搞orderedPostProcessors         List orderedPostProcessors = new ArrayList();        for (String postProcessorName : orderedPostProcessorNames) {            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));        }        sortPostProcessors(beanFactory, orderedPostProcessors);        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);        // 搞普通的BeanFactoryPostProcessors.        List nonOrderedPostProcessors = new ArrayList();        for (String postProcessorName : nonOrderedPostProcessorNames) {            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));        }        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);        // 清除緩存數據        beanFactory.clearMetadataCache();    }

整個過程,其實還蠻清晰流暢的嘛

好了,接下來我們看下refresh里面下一個函數, 同樣又是重量級嘉賓, 但是,當你看懂了beanFactory的后置處理器,來分析這段代碼,簡直小菜一碟

registerBeanPostProcessors(beanFactory)

    public static void registerBeanPostProcessors(            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {        // 首先拿到所有的BeanPostProcessor        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);        // 這里可以不用細看,主要是做postProcessor的check        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));        // 開始分類        List priorityOrderedPostProcessors = new ArrayList();        // 主要保存MergedBeanDefinitionPostProcessor這以特殊的后置處理器        List internalPostProcessors = new ArrayList();        List orderedPostProcessorNames = new ArrayList();        List nonOrderedPostProcessorNames = new ArrayList();        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);            }        }        // 對實現了PriorityOrdered的BeanPostProcessor排序        sortPostProcessors(beanFactory, priorityOrderedPostProcessors);        // 注冊實現了PriorityOrdered的BeanPostProcessor        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);        // 拿到實現了Ordered接口的BeanPostProcessor         List orderedPostProcessors = new ArrayList();        for (String ppName : orderedPostProcessorNames) {            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);            orderedPostProcessors.add(pp);            // 如果這個BeanPostProcessor還實現了BeanPostProcessor接口,保留下來            if (pp instanceof MergedBeanDefinitionPostProcessor) {                internalPostProcessors.add(pp);            }        }        // 對實現了PriorityOrdered接口的BeanPostProcessor排序        sortPostProcessors(beanFactory, orderedPostProcessors);        // 注冊實現了PriorityOrdered接口的BeanPostProcessor        registerBeanPostProcessors(beanFactory, orderedPostProcessors);        // 拿到普通的BeanPostProcessor        List nonOrderedPostProcessors = new ArrayList();        for (String ppName : nonOrderedPostProcessorNames) {            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);            nonOrderedPostProcessors.add(pp);            // 如果這個BeanPostProcessor還實現了MergedBeanDefinitionPostProcessor接口,保留下來            if (pp instanceof MergedBeanDefinitionPostProcessor) {                internalPostProcessors.add(pp);            }        }        // 注冊普通的BeanPostProcessor        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);        // 注冊實現了MergedBeanDefinitionPostProcessor的接口,聰明的讀者一定會有疑問,這里難道不會重復注冊嗎?        // 答案是不會, 因為注冊的時候會先將之前注冊的刪掉的,我這么做的原因只是為了分類處理而已, 要將所有的        // MergedBeanDefinitionPostProcessor 放到最后處理        sortPostProcessors(beanFactory, internalPostProcessors);        registerBeanPostProcessors(beanFactory, internalPostProcessors);        // 最后,添加了一個特殊的后置處理器, 那么這個后置處理器必然最后一個被處理        // 用來注冊實現了ApplicationListener接口的bean        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));    }

從上面的步驟可以看出和invokeBeanFactoryPostProcessors(beanFactory);的區別就是這邊只是做一個注冊而已,因為
BeanPostProcessor的功能是在bean初始化前后做一些手腳,那這邊bean還沒初始化呢,調用了有個毛用啊?

回到refresh() 繼續下面一行

initMessageSource();

這一行主要是拿到與i18n,即國際化相關的bean, 如果你定義了,我就拿過來注冊上去,如果沒有定義, 那么我就自己搞出來一個空的,
所有的實現都是繼承自父bean

    protected void initMessageSource() {        // 拿到工廠        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {        // 如果你定義,就拿過來            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);            // 如果我有父親,并且這個國際化的bean也有層次, 那么就將我父親的國際化bean設置為這個國際化bean的父親            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;                if (hms.getParentMessageSource() == null) {                    hms.setParentMessageSource(getInternalParentMessageSource());                }            }            if (logger.isDebugEnabled()) {                logger.debug(Using MessageSource [ + this.messageSource + ]);            }        }        else {        //  定義一個空的            DelegatingMessageSource dms = new DelegatingMessageSource();            // 我將我父親的國際化bean拿來作為這個空的國際化bean,這樣所有的國際化操作都通過我父親的國際化bean            dms.setParentMessageSource(getInternalParentMessageSource());            this.messageSource = dms;            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);            if (logger.isDebugEnabled()) {                logger.debug(Unable to locate MessageSource with name ' + MESSAGE_SOURCE_BEAN_NAME +                        ': using default [ + this.messageSource + ]);            }        }    }

繼續refresh() 中的下一行

initApplicationEventMulticaster()

注冊事件管理器bean,和上面國際化bean差不多的實現, 如果你注冊了,我就直接拿來用,否則我就自己創建一個默認的

    protected void initApplicationEventMulticaster() {        ConfigurableListableBeanFactory beanFactory = getBeanFactory();        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {            this.applicationEventMulticaster =                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);            if (logger.isDebugEnabled()) {                logger.debug(Using ApplicationEventMulticaster [ + this.applicationEventMulticaster + ]);            }        }        else {            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);            if (logger.isDebugEnabled()) {                logger.debug(Unable to locate ApplicationEventMulticaster with name ' +                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +                        ': using default [ + this.applicationEventMulticaster + ]);            }        }    }

refresh()方法下一行

onRefresh();

    protected void onRefresh() throws BeansException {        // For subclasses: do nothing by default.    }

里面啥都沒,又是為了給我子類作為擴展!!

繼續refresh()方法下一行

registerListeners();

就是注冊事件監聽器啦, 也沒啥牛逼的

    protected void registerListeners() {        // 先注冊你手工注冊的監聽器        for (ApplicationListener listener : getApplicationListeners()) {            getApplicationEventMulticaster().addApplicationListener(listener);        }        // 再注冊在配置文件或者注解里面的監聽器        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);        for (String listenerBeanName : listenerBeanNames) {            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);        }        // 因為到了這里,我們終于有了一個事件管理器了,我們早先定義的earlyApplicationEvents        // 可以下崗了,下崗之前,別忘了要把它手中的任務先完成哦        Set earlyEventsToProcess = this.earlyApplicationEvents;        this.earlyApplicationEvents = null;        if (earlyEventsToProcess != null) {            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {                getApplicationEventMulticaster().multicastEvent(earlyEvent);            }        }    }

繼續refresh()方法下一行

finishBeanFactoryInitialization(beanFactory);

在這個函數中,我把那些需要提前實例化的bean預先實例化, 啥叫需要提前實例化?要滿足三個條件, 非抽象并且lazy-init為false
的單例

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {        // 注冊轉換服務, 這個和之前提到的屬性編輯器是差不多的東西        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {            beanFactory.setConversionService(                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));        }        // 和AOP相關的功能, 先忽略吧        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);        for (String weaverAwareName : weaverAwareNames) {            getBean(weaverAwareName);        }        // 待定...        beanFactory.setTempClassLoader(null);        // 凍結所有的配置, 不能再修改任何配置啦, 因為接下來我就要實例化bean了啊!!        beanFactory.freezeConfiguration();        // 實例化需要實例化的bean        beanFactory.preInstantiateSingletons();    }

關于實例化bean,之后會詳細分析.
我們可以看到,我在處理bean的時候,是先將配置文件或者注解什么的元數據(BeanDefinition)先準備好, 在實例化bean之前,又留了
兩大擴展 BeanFactoryPostProcessor 和BeanPostProcessor 給你做擴展, 最后,我的依賴關系也是在實例化bean的時候完成的,之前
準備BeanDefinition的時候并沒有去解決依賴關系,只是聲明了,啊,誰依賴誰,這樣子.

refresh() 下一行, 終于結束整個上下文的刷新啦!

finishRefresh();

    protected void finishRefresh() {        // 初始化生命周期處理器, 和注冊國際化bean以及事件監聽器一個套路了        initLifecycleProcessor();        // 生命周期處理器開始工作啦,如果你的bean實現了lifecycle接口, 并且現在是非運行狀態,它會調用你的run方法哦        getLifecycleProcessor().onRefresh();        // 宣告天下,上下文刷新成功,跪舔吧,騷年!!        publishEvent(new ContextRefreshedEvent(this));        // 待定        LiveBeansView.registerApplicationContext(this);    }

以上任何異步出現異常,我都會清理掉這個過程中產生的垃圾,并把工廠關閉!由下面幾行異常處理函數來處理

    catch (BeansException ex) {        logger.warn(Exception encountered during context initialization - cancelling refresh attempt, ex);        // 銷毀這個過程中產生的bean,因為產生的bean可能是殘廢的(依賴關系沒有注入成功的)        destroyBeans();        // 關掉這個場吧        cancelRefresh(ex);        throw ex;    }

最終,將一些common的緩存清理掉, 這里我還得繼續研究&hellip;

            finally {                // Reset common introspection caches in Spring's core, since we                // might not ever need metadata for singleton beans anymore...                resetCommonCaches();            }

至此,我的核心框架已經全部向你展示完畢,怎樣?是不是so easy, 接下來,我會詳細剖析每一個部分的實現細節,敬請期待!

歡迎加群了解如何開始你的第一份源碼之旅

QQ群290551701 聚集很多互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志于從事IT行業人員進入!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安岳县| 岱山县| 福贡县| 重庆市| 伊宁市| 元谋县| 寿光市| 梧州市| 巴彦县| 北票市| 老河口市| 绍兴县| 元阳县| 张家川| 丹东市| 巴东县| 舞钢市| 苍梧县| 衡东县| 喀喇沁旗| 馆陶县| 噶尔县| 太仆寺旗| 正定县| 焦作市| 高台县| 齐河县| 旌德县| 若尔盖县| 冀州市| 霍邱县| 修文县| 赤壁市| 江永县| 公安县| 沽源县| 泗洪县| 西和县| 辽阳县| 三门峡市| 中山市|