Spring 核心源碼

一、Spring的優(yōu)勢及核心

? ? 1、Spring通過DI、AOP和消除樣板式代碼來簡化企業(yè)級Java開發(fā)。
????2、Spring框架之外還存在一個(gè)構(gòu)建在核心框架之上的龐大生態(tài)圈,它將Spring擴(kuò)展到不同的領(lǐng)域,如Web服務(wù)、REST、移動(dòng)開發(fā)以及NoSQL等。
????3、低侵入式設(shè)計(jì),代碼的污染極低。
????4、獨(dú)立于各種應(yīng)用服務(wù)器,基于Spring框架的應(yīng)用,可以真正實(shí)現(xiàn)Write Once,Run Anywhere的承諾。
????5、Spring的IOC容器降低了業(yè)務(wù)對象替換的復(fù)雜性,提高了組件之間的解耦。
????6、Spring的AOP允許將一些通用任務(wù)如安全、事務(wù)、日志等進(jìn)行集中式處理,從而提供了更好的復(fù)用。
????7、Spring的ORM和DAO提供了與第三方持久層框架的的良好整合,并簡化了底層的數(shù)據(jù)庫訪問。
????8、Spring的高度開放性,并不強(qiáng)制應(yīng)用完全依賴于Spring,開發(fā)者可自由選用Spring框架的部分或全部。
? ? Spring的核心就是IOC和AOP
? ? ? ? IOC:控制反轉(zhuǎn),就是應(yīng)用本身不負(fù)責(zé)以來對象的創(chuàng)建和維護(hù),依賴對象的創(chuàng)建及維護(hù)交由外部容器負(fù)責(zé)的,這樣控制權(quán)就由應(yīng)用轉(zhuǎn)移到了外部容器,控制權(quán)的轉(zhuǎn)移。
? ? ? ? DI:依賴注入,指在程序運(yùn)行期間,由外部容器動(dòng)態(tài)地將依賴對象注入到組件中,一般通過構(gòu)造函數(shù)或者setter方法注入。
? ? ? ? AOP:面向切面編程,在不改變原有代碼的情況下,增強(qiáng)和主要業(yè)務(wù)無關(guān)的公共代碼到之前寫好的方法中的指定位置。

二、XML配置啟動(dòng)代碼

// 在ClassPath中尋找XML配置文件,根據(jù)xml文件內(nèi)容來構(gòu)建ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationfile.xml");

? ? 1、當(dāng)然,ApplicationContext的實(shí)現(xiàn)類不只有ClassPathXmlApplicationContext,他擁有一套繼承類,各有優(yōu)缺點(diǎn)。


ApplicationContext 繼承結(jié)構(gòu)



? ? FileSystemXmlApplicationContext的構(gòu)造函數(shù)需要一個(gè)xml配置文件在系統(tǒng)中的路徑,其他和ClassPathXmlApplicationContext基本一致
? ? AnnotationConfigApplicationContext是基于注解來使用的,他不需要配置文件,采用Java配置類和各種注解來配置,是比較簡單的方式

? ? 2、怎么實(shí)例化ApplicationContext:
? ? ? ? 一個(gè)接口和他的實(shí)現(xiàn)類:

public interface UserService {
? ? User select(Integer id)
}

//實(shí)現(xiàn)類

@Service
public class UserServiceImpl implements UserService{
????public void select(Integer id){
?????????System.out.println("查詢User");
????}
}

? ? ? ? 然后在resource目錄下新建一個(gè)配置文件,可以叫spring.xml 或application.xml等,名字隨意,最好按照普遍規(guī)范來。

<?xml version="1.0" encoding="UTF-8" ?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
?????<bean id="UserService" class="com.engine.service.UserServiceImpl"/>
</beans>

? ? ? ? 最后創(chuàng)建一個(gè)測試類就可以了

@Testpublic void test() throws Exception {
?????ClassPathXmlApplicationContext ioc=new ClassPathXmlApplicationContext("classpath:/spring.xml");
? ? ?UserService bean = (UserService) ioc.getBean(UserService.class);
?????bean.select(1);
}

????這樣就可以了,這部分具體內(nèi)容可以看看Spring IOC的基礎(chǔ)知識。

三、BeanFactory 簡介

? ? 顧名思義,Bean的生成工廠,負(fù)責(zé)生產(chǎn)和管理各個(gè)bean實(shí)例的。

BeanFactory相關(guān)主要繼承結(jié)構(gòu)

? ? 這里面包括了上一張圖的ApplicationContext繼承結(jié)構(gòu),感覺看起來還是很亂的??,我們重點(diǎn)關(guān)注一下幾個(gè)類就好。
? ??ApplicationContext,繼承了ListableBeanFactory,Listable是通過這個(gè)接口,可以獲取到多個(gè)Bean,而最頂層的BeanFactory接口方法都是獲取的單個(gè)Bean。
? ? ? ? 還繼承了HierarchicalBeanFactory,Hierarchical單詞有點(diǎn)難度了,他是分等級的,等級制度的意思,也就是說我們可以在應(yīng)用中起多個(gè)BeanFactory,然后將他們之間設(shè)置為父子關(guān)系。
? ??AutowireCapableBeanFactory,看到名字就懷疑他是不是跟@Autowire注解有什么關(guān)系呢,他就是用來自動(dòng)裝配Bean的,雖然ApplicationContext與他并沒有直接繼承關(guān)系,但是ApplicationContext接口中的最后一個(gè)方法將他們聯(lián)系起來了:AutowireCapableBeanFactorygetAutowireCapableBeanFactory() throws IllegalStateException;
????ConfigurableListableBeanFactory 也是一個(gè)特殊的接口,看圖,特殊之處在于它繼承了第二層所有的三個(gè)接口,而 ApplicationContext 沒有。

四、啟動(dòng)過程分析

? ? 1、ClassPathXmlApplicationContext的構(gòu)造方法

// 這里包含了啟動(dòng)過程的核心方法,也是我們接下來的重點(diǎn)方法?refresh();
// ApplicationContext 建立起來以后,是可以通過refresh()這個(gè)方法重建的,refresh()會(huì)將原來的ApplicationContext銷毀,
// 然后在重新執(zhí)行一次初始化操作
public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
?????super(parent);
?????setConfigLocations(configLocations);
?????if (refresh) {
?????????refresh();
?????}
}

? ? 2、refresh()方法的內(nèi)容:

public void refresh() throws BeansException, IllegalStateException {
?????// 來個(gè)鎖,不然 refresh() 還沒結(jié)束,你又來個(gè)啟動(dòng)或銷毀容器的操作,那不就亂套了嘛
?????synchronized (this.startupShutdownMonitor) {
?????????// 準(zhǔn)備工作,記錄下容器的啟動(dòng)時(shí)間、標(biāo)記“已啟動(dòng)”狀態(tài)、處理配置文件中的占位符

?????????prepareRefresh();
?????????// 這步比較關(guān)鍵,這步完成后,配置文件就會(huì)解析成一個(gè)個(gè) Bean 定義,注冊到 BeanFactory 中,
?????????// 當(dāng)然,這里說的 Bean 還沒有初始化,只是配置信息都提取出來了,
?????????// 注冊也只是將這些信息都保存到了注冊中心(說到底核心是一個(gè) beanName-> beanDefinition 的 map)
?????????ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

?????????// 設(shè)置 BeanFactory 的類加載器,添加幾個(gè) BeanPostProcessor,手動(dòng)注冊幾個(gè)特殊的 bean
? ? ? ? ?prepareBeanFactory(beanFactory); try {
?????????????// 【這里需要知道 BeanFactoryPostProcessor 這個(gè)知識點(diǎn),Bean 如果實(shí)現(xiàn)了此接口,
?????????????// 那么在容器初始化以后,Spring 會(huì)負(fù)責(zé)調(diào)用里面的 postProcessBeanFactory 方法?!?br>?????????????// 這里是提供給子類的擴(kuò)展點(diǎn),到這里的時(shí)候,所有的 Bean 都加載、注冊完成了,但是都還沒有初始化
?????????????// 具體的子類可以在這步的時(shí)候添加一些特殊的 BeanFactoryPostProcessor 的實(shí)現(xiàn)類或做點(diǎn)什么事
?????????????postProcessBeanFactory(beanFactory);

?????????????// 調(diào)用 BeanFactoryPostProcessor 各個(gè)實(shí)現(xiàn)類的 postProcessBeanFactory(factory) 方法
?????????????invokeBeanFactoryPostProcessors(beanFactory);

?????????????// 注冊 BeanPostProcessor 的實(shí)現(xiàn)類,注意看和 BeanFactoryPostProcessor 的區(qū)別
?????????????// 此接口兩個(gè)方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
?????????????// 兩個(gè)方法分別在 Bean 初始化之前和初始化之后得到執(zhí)行。注意,到這里 Bean 還沒初始化
?????????????registerBeanPostProcessors(beanFactory);

?????????????initMessageSource();
?????????????// 初始化當(dāng)前 ApplicationContext 的事件廣播器,這里也不展開了 initApplicationEventMulticaster();
?????????????// 從方法名就可以知道,典型的模板方法(鉤子方法),
?????????????// 具體的子類可以在這里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
?????????????onRefresh();
?????????????// 注冊事件監(jiān)聽器,監(jiān)聽器需要實(shí)現(xiàn) ApplicationListener 接口。這也不是我們的重點(diǎn),過 registerListeners();
?????????????// 重點(diǎn),重點(diǎn),重點(diǎn)
? ? ? ? ? ? ? // 初始化所有的 singleton beans
?????????????//(lazy-init 的除外)
?????????????finishBeanFactoryInitialization(beanFactory);
?????????????// 最后,廣播事件,ApplicationContext 初始化完成
?????????????finishRefresh();
?????????} catch (BeansException ex) {
?????????????if (logger.isWarnEnabled()) {
?????????????????logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);
?????????????}
?????????????????// Destroy already created singletons to avoid dangling resources.
?????????????????// 銷毀已經(jīng)初始化的 singleton 的 Beans,以免有些 bean 會(huì)一直占用資源
?????????????destroyBeans();
?????????????// Reset 'active' flag.
?????????????cancelRefresh(ex);
?????????????// 把異常往外拋
?????????????throw ex;
?????????} finally {?
????????????// Reset common introspection caches in Spring's core, since we
?????????????// might not ever need metadata for singleton beans anymore...
?????????????resetCommonCaches();
?????????}
?????}
}?

? ? 這個(gè)方法中調(diào)用了很多的其他方法,我們來一步一步介紹。
? ? 1、創(chuàng)建Bean前的準(zhǔn)備工作

prepareRefresh方法源碼

? ? ????這個(gè)類實(shí)現(xiàn)的比較簡單,先是記錄了一下啟動(dòng)時(shí)間,然后校驗(yàn)一下配置文件。
? ? 2、創(chuàng)建Bean容器,加載并注冊Bean
? ? ? ? 然后我們走到下一行:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
? ? ? ? 這個(gè)方法是全文中最重要的一部分之一,這里將會(huì)初始化BeanFactory、加載Bean、注冊Bean等等,當(dāng)然Bean的實(shí)例并不是在這一步生成的。這里源碼就不貼了,感興趣的小伙伴可以自己去項(xiàng)目中研究一下吧。
? ??????ApplicationContext 繼承自 BeanFactory,但是它不應(yīng)該被理解為 BeanFactory 的實(shí)現(xiàn)類,而是說其內(nèi)部持有一個(gè)實(shí)例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相關(guān)的操作其實(shí)是委托給這個(gè)實(shí)例來處理的。

? ? 3、BeanDefinition 接口定義
? ??????常說 BeanFactory 是 Bean 容器,那么 Bean 又是什么呢?BeanDefinition 就是我們所說的 Spring 的 Bean,我們自己定義的各個(gè) Bean 其實(shí)會(huì)轉(zhuǎn)換成一個(gè)個(gè) BeanDefinition 存在于 Spring 的 BeanFactory 中。Bean 在代碼層面上可以簡單認(rèn)為是 BeanDefinition 的實(shí)例。BeanDefinition 中保存了我們的 Bean 信息,比如這個(gè) Bean 指向的是哪個(gè)類、是否是單例的、是否懶加載、這個(gè) Bean 依賴了哪些 Bean 等等。

customizeBeanFactory

? ? ? ? 這個(gè)方法就是配置是否允許 BeanDefinition 覆蓋、是否允許循環(huán)引用。

加載 Bean: loadBeanDefinitions

????這個(gè)方法會(huì)根據(jù)配置加載各個(gè)Bean,然后放到BeanFactory中,讀取配置的操作在XmlBeanDefinitionReader中,其負(fù)責(zé)加載配置、解析。


未完待續(xù)~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容