上一期,我們簡(jiǎn)單分析了下spring的@Autowired注解的原理,這一次,我們?cè)俅畏治鰏pring的源碼,大家還接的我們最初使用spring的時(shí)候
都是要在配置文件配置bean,然后才能使用,現(xiàn)在慢慢的這個(gè)xml的配置方式已經(jīng)淘汰了,現(xiàn)在基本上都是使用springboot了,這次那,為了看
源碼方便,我們就從最開(kāi)始的配置文件加載來(lái)分析下
大家可以看到以下代碼,我將springApplication.run方法注釋掉了,就專(zhuān)門(mén)定義一個(gè)xml配置文件,然后加載這個(gè)配置文件,看看spring怎樣一步步
完成容器的創(chuàng)建,屬性賦值操作,等等
@SpringBootApplication
@MapperScan("com.ryx.xiaoxin_distribute.mapper")
@EnableCaching
@EnableTransactionManagement
public class XiaoxinDistributeApplication {
public static void main(String[] args) {
//SpringApplication.run(XiaoxinDistributeApplication.class, args);
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:application-hellospring.xml");
System.out.println("applicationContext啟動(dòng)了....");
// 從上下文中獲取bean
HelloSpring helloSpring = applicationContext.getBean(HelloSpringImpl.class);
System.out.println(helloSpring.sayHello());
}
}
#Xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<bean id="helloSpring" class="com.ryx.xiaoxin_distribute.spring.springIocAndAop.IOC.test1.HelloSpringImpl"/>
</beans>
在aplicationContext的繼承體系中,我們會(huì)發(fā)現(xiàn)aplicationContext繼承了BeanFactory,所以我們也可以說(shuō)ApplicationContext就是BeanFactory
BeanFactory到底是什么,你翻譯成Bean工廠,或者Bean容器,都沒(méi)有問(wèn)題,其實(shí)就是為我們生產(chǎn)各種我們需要的Bean,讓我們使用,在生產(chǎn)的過(guò)程中,
要處理各種依賴(lài)問(wèn)題,所以又引入了依賴(lài)注入,其實(shí)就是解決bean在生成我們需要的bean的時(shí)候?yàn)榱私鉀Q依賴(lài)問(wèn)題所產(chǎn)生的的一種處理方式
試想一下,在沒(méi)有BeanFactory的時(shí)候,對(duì)象之間的依賴(lài)關(guān)系,緊緊的耦合在一起,這種依賴(lài)關(guān)系必須我們自己維護(hù),然后就是各種new,但是spring出現(xiàn)之后
就告訴我們,你不用管各個(gè)類(lèi)之間的依賴(lài)了,我來(lái)幫你搞定,你只需要關(guān)注業(yè)務(wù)邏輯即可,還有一點(diǎn),最最重要的,我們終于可以不用new了,因?yàn)槎伎梢酝ㄟ^(guò)
beanFactory實(shí)例化好了,還有一點(diǎn),beanFctory在實(shí)例化bean的過(guò)程中(生命周期內(nèi)),為我們提供了各種街口,讓我們有能力在bean的生命周期內(nèi)為所欲為
總結(jié)下:
1:applicationContext就是一個(gè)beanFactory
2:beanFactory為我們解決了各個(gè)對(duì)象之間的依賴(lài)關(guān)系,達(dá)到松耦合的目的
3:我們不用在new對(duì)象了,
4:可以通過(guò)spring提供的各種接口在bean的生命周期內(nèi)對(duì)bean做各種啊操作
接下來(lái),我們跟著bean的啟動(dòng)來(lái)一探究竟
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
//初始化父類(lèi)content
super(parent);
//設(shè)置xml的配置路徑
setConfigLocations(configLocations);
//刷新上下文
if (refresh) {
refresh();
}
}
@Override
public void refresh() throws BeansException, IllegalStateException {
//使用同步鎖機(jī)制,防止容器并發(fā)刷新
synchronized (this.startupShutdownMonitor) {
//一: 預(yù)刷新操作,1:記錄容器啟動(dòng)的時(shí)間2:處理屬性的占位符3:校驗(yàn)屬性是否可以解析
prepareRefresh();
// 二:定義bean工廠解析xml文件中的bean內(nèi)容為map(BeandefinitionMap)的形式并將其注冊(cè)到beanFctory中于格式
//key:helloSprin value:com.ryx.xiaoxin_distribute.spring.springIocAndAop.IOC.test1.HelloSpringImpl
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 三:設(shè)置類(lèi)加載器,手動(dòng)注冊(cè)系統(tǒng)屬性的bean
prepareBeanFactory(beanFactory);
try {
//四:加載BeanFactoryPostProcessor ,對(duì)bean工廠執(zhí)行后置處理
postProcessBeanFactory(beanFactory);
// 五:加載實(shí)現(xiàn)了beanFactoryPostProcessors的方法
invokeBeanFactoryPostProcessors(beanFactory);
// 六:注冊(cè)并實(shí)例化所有實(shí)現(xiàn)了BeanPostProcessor接口的實(shí)現(xiàn)類(lèi)
registerBeanPostProcessors(beanFactory);
// 七:初始化MessageSource
initMessageSource();
// 八:為此上下文初始化事件多播器
initApplicationEventMulticaster();
//九:在特定上下文子類(lèi)中初始化其他特殊bean
onRefresh();
// 十:注冊(cè)監(jiān)聽(tīng)器bean
registerListeners();
// 十一:初始化所有的單例bean
finishBeanFactoryInitialization(beanFactory);
// 十二:發(fā)布相應(yīng)的事件,初始化完成
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 十三:
destroyBeans();
// 十四:
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
可以看到,spring的12個(gè)比較重要的方法,我都簡(jiǎn)單注明了下屬性,本想在一篇文章寫(xiě)完這些步驟,但是內(nèi)容實(shí)在太多,我會(huì)按照一個(gè)步驟一篇文章的形式,來(lái)分析spring的源碼,希望我的文章會(huì)對(duì)你有一點(diǎn)點(diǎn)的幫助,本期文章是一個(gè)先導(dǎo)片,下一篇開(kāi)始,我會(huì)具體分析spring的步驟哈!
Thanks!