1.概念
- 控制反轉(zhuǎn)
對(duì)于軟件來(lái)說,調(diào)用類依賴于某一接口的實(shí)現(xiàn)類勒虾。但是現(xiàn)在將控制權(quán)從調(diào)用類移除停撞,轉(zhuǎn)而由第三方?jīng)Q定,即由Spring容器借由Bean配置來(lái)進(jìn)行控制转绷。
- 依賴注入
調(diào)用類對(duì)某一接口實(shí)現(xiàn)類的依賴關(guān)系由第三方(容器或協(xié)作類)注入伟件,以移除調(diào)用類對(duì)某一接口實(shí)現(xiàn)類的依賴。
- IOC類型
- 構(gòu)造函數(shù)注入
- 屬性注入
- 接口注入
2.Java反射的基本知識(shí)
Java語(yǔ)言允許通過程序化的方式間接對(duì)Class進(jìn)行操作议经。Class文件由類裝載器裝載后斧账,在JVM中將形成一份描述Class結(jié)構(gòu)的元信息對(duì)象,通過該元信息對(duì)象可以獲知Class的結(jié)構(gòu)信息煞肾,如構(gòu)造函數(shù)咧织、屬性和方法等。Java允許用戶借由這個(gè)與Class相關(guān)的元信息對(duì)象間接調(diào)用Class對(duì)象的功能籍救。
反射的步驟
- 通過類裝載器獲取對(duì)象
- 獲取對(duì)象的默認(rèn)構(gòu)造器對(duì)象并通過它實(shí)例化對(duì)象
- 通過反射獲取方法习绢,并且通過方法設(shè)置屬性
Java反射機(jī)制
- Constructor(類的構(gòu)造函數(shù)反射類)
- Method(類方法的反射類)
- Field(類的成員變量的反射類)
3.資源訪問利器
3.1資源訪問接口
Spring設(shè)計(jì)了一個(gè)Resource接口,它能夠提供更強(qiáng)的底層資源訪問
訪問類路徑下的web應(yīng)用的三種方式
- 通過FileSystemResource以文件系統(tǒng)絕對(duì)路徑的方式進(jìn)行訪問
- 通過ClassPathResource以類路徑的方式進(jìn)行訪問
- 通過ServletContextResource以相對(duì)于Web應(yīng)用根目錄的方式進(jìn)行訪問
public static void main(String[] args) throws IOException {
String filePath = "I:/網(wǎng)絡(luò)資源/Idea--space/SpringDemo/src/main/resources/test_input.txt";
//使用系統(tǒng)文件路徑方式加載文件
WritableResource res1 = new PathResource(filePath);
//使用類路徑方式加載文件
Resource res2 = new ClassPathResource("resources/test_input.txt");
//使用WritableResurce接口寫資源文件
OutputStream stream1 = res1.getOutputStream();
stream1.write("歡迎光臨\n小春論壇".getBytes());
stream1.close();
//使用Resource接口讀資源文件
InputStream in1 = res1.getInputStream();
//InputStream in2 = res2.getInputStream();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
int i;
while((i=in1.read())!=-1){
baos.write(i);
}
System.out.println("res1"+res1.getFilename());
System.out.println("res2"+res2.getFilename());
}
public static void main(String[] args) throws IOException {
//當(dāng)系統(tǒng)加載時(shí)默認(rèn)采用系統(tǒng)編碼讀取資源內(nèi)容钧忽,如果資源采用特殊的編碼格式可以通過EncodedResource對(duì)資源進(jìn)行編碼毯炮,以保證資源內(nèi)容操作的正確性
String filePath = "I:/網(wǎng)絡(luò)資源/Idea--space/SpringDemo/src/main/resources/test_input.txt";
//使用系統(tǒng)文件路徑方式加載文件
WritableResource res1 = new PathResource(filePath);
//Resource res = new ClassPathResource("resources/test_input.txt");
EncodedResource encRes=new EncodedResource(res1,"utf-8");
String content= FileCopyUtils.copyToString(encRes.getReader());
System.out.println(content);
}
3.2資源加載
Spring 提供了一個(gè)強(qiáng)大的加載資源的機(jī)制逼肯,不但可以通過"classpath:"、"file:"等資源前綴識(shí)別不同的資源類型桃煎,還支持帶Ant風(fēng)格帶通配符的資源地址(可以在不顯示使用Resource實(shí)現(xiàn)類的情況下篮幢,僅通過資源地址的特殊標(biāo)識(shí)符就可以訪問相應(yīng)的資源)
地址前綴 | 對(duì)應(yīng)的資源類型 |
---|---|
classpath: | 從類路徑中加載資源,classpath:和classpath:/是等價(jià)的 |
file: | 使用UrlResource從文件系統(tǒng)目錄中裝載資源为迈,可采用絕對(duì)或相對(duì)路徑 |
http: | 使用UrlResource從Web服務(wù)器中裝載資源 |
ftp: | 使用UrlResource從FTP服務(wù)器中裝載資源 |
沒有前綴 | 根據(jù)ApplicationContext的具體實(shí)現(xiàn)采用對(duì)應(yīng)類型的Resource |
Ant風(fēng)格的資源配置地址支持3種匹配符
- ?:匹配文件名中的一個(gè)字符
- *:匹配文件名中的任意字符
- **:匹配多層路徑
4三椿、BeanFactory和ApplicationContext
Spring 通過一個(gè)配置文件描述Bean和Bean之間的依賴關(guān)系,利用Java語(yǔ)言的反射功能實(shí)例化Bean并建立Bean之間的依賴關(guān)系葫辐。Spring的IOC容器在完成這些底層工作的基礎(chǔ)上搜锰,還提供了Bean實(shí)例緩存,聲明周期管理耿战,Bean實(shí)例代理蛋叼,事件發(fā)布,資源裝載等高級(jí)服務(wù)剂陡。我們一般稱BeanFactory為IOC容器狈涮,而稱ApplicationContext為應(yīng)用上下文。
對(duì)于兩者的用途鸭栖,我們可以進(jìn)行簡(jiǎn)單的劃分:BeanFactory是Spring框架的基礎(chǔ)設(shè)施歌馍,面向Spring本身;ApplicationContext面向使用Spring框架的開發(fā)者晕鹊,幾乎所有的使用場(chǎng)合都可以直接使用ApplicationContext而非底層的BeanFactory
4.1.BeanFactory介紹
接口中最重要的方法getBean(String beanName),該方法從容器中返回特定名稱的
bean
和BeanFactory有關(guān)的接口說明
- ListableBeanFactory:該接口定義了訪問容器中Bean基本信息的若干方法松却,如查看Bean的個(gè)數(shù)
- HierarchicalBeanFactory:父子級(jí)聯(lián)Ioc容器的接口,子容器可以通過接口方法訪問父容器
- ConfigurableBeanFactory:增強(qiáng)了Ioc容器的可定制性溅话。它定義了設(shè)置類裝載器晓锻、屬性編輯器、容器初始化后置處理器等方法
- AutowireCapableBeanFactory:定義了將容器中的Bean按某種規(guī)則(如按名字匹配公荧、按類型匹配等)進(jìn)行自動(dòng)裝配的方法
- SingletonBeaRegistry:定義了允許在運(yùn)行期間向容器注冊(cè)單實(shí)例Bean的方法
- BeanDefinitionRegister:Spring配置文件中每一個(gè)<bean>節(jié)點(diǎn)元素在Spring容器里都通過一個(gè)BeanDefinition對(duì)象表示带射,它描述了Bean的配置信息。
4.2.ApplicationContext介紹
ApplicationContext類體系結(jié)構(gòu),ApplicationContext的主要實(shí)現(xiàn)類是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默認(rèn)從類路徑加載配置文件循狰,后者默認(rèn)從系統(tǒng)中中裝載配置文件窟社,擴(kuò)展BeanFactory的功能的相關(guān)接口
- ApplicationEventPublisher:讓容器擁有發(fā)布應(yīng)用上下文事件的功能,包括容器啟動(dòng)事件绪钥、關(guān)閉事件等灿里。
- MessageSource:為應(yīng)用提供il8n國(guó)際化消息訪問的功能
- ResourcePatternResolver:所有ApplicationContext實(shí)現(xiàn)類都實(shí)現(xiàn)了類似于PathMatchingResourcePatternResolver的功能,可以通過帶前綴的Ant風(fēng)格的資源文件路徑裝載Spring的配置文件
- LifeCycle:該接口提供了start()和stop()兩個(gè)方法程腹,主要用于控制異步處理過程匣吊。在具體使用時(shí),該接口同時(shí)被ApplicationContext實(shí)現(xiàn)及具體Bean實(shí)現(xiàn),ApplicationContext會(huì)將start/stop的信息傳遞給容器中所有實(shí)現(xiàn)了該接口的Bean,以達(dá)到管理和控制JMX色鸳、任務(wù)調(diào)度等目的社痛。
ConfigurableApplicationContext擴(kuò)展與ApplicationContext,它新增了兩個(gè)主要的方法:refresh和close。在應(yīng)用上下文關(guān)閉的情況下調(diào)用refresh可以啟動(dòng)應(yīng)用上下文命雀,在已經(jīng)啟動(dòng)的狀態(tài)下調(diào)用可以清楚緩存蒜哀,并重新裝載配置信息,調(diào)用close則可以關(guān)閉應(yīng)用上下文吏砂。
4.3.WebApplicationContext類體系結(jié)構(gòu)
WebApplicationContext是專門為Web應(yīng)用準(zhǔn)備的撵儿,它允許從相對(duì)于Web根目錄的路徑中裝載配置文件完成初始化工作,從WebApplicationContext中可以獲得ServletContext的引用狐血,整個(gè)Web應(yīng)用的上下文對(duì)象將作為屬性放置到ServletContext中淀歇,以便Web應(yīng)用環(huán)境可以訪問Spring上下文。Spring專門為此提供了一個(gè)工具類WebApplicationContextUtils匈织,通過該類的getWebApplicationContext(ServletContext sc)方法浪默,可以從Ser
vletContext中獲取WebApplicationContext實(shí)例。
WebApplicationContext的初始化不同于BeanFactory和ApplicationContext缀匕,因?yàn)閃ebApplicationContext需要ServletContext實(shí)例浴鸿,也就是說,它必須在擁有Web容器的前提下才能完成啟動(dòng)工作弦追。
5、父子容器
Spring的IOC容器可以建立父子層級(jí)關(guān)聯(lián)的容器體系花竞,子容器可以訪問父容器中的Bean劲件,但父容器不能訪問子容器中的Bean。
5.1.Bean的生命周期
BeanFactory中Bean的生命周期约急,具體的調(diào)用過程如下
- 調(diào)用者通過getBean請(qǐng)求Bean時(shí)零远,如果容器注冊(cè)了InstantiationAwareBeanPostprossor接口,在實(shí)例化之前會(huì)調(diào)用接口的postProcessBeforeInstantiation方法
- 根據(jù)配置情況實(shí)例化Bean
- 如果容器注冊(cè)了InstantiationAwareBeanPostProcessor接口厌蔽,在實(shí)例化Bean之后牵辣,調(diào)用該接口的postProcessorAfterInstantiation方法
- 將屬性信息配置在Bean中,在設(shè)置每個(gè)屬性之前奴饮,先調(diào)用InstantiationAwareBeanPostProcess接口的postProcessPropertyValues方法
- 調(diào)用Bean的屬性設(shè)置方法設(shè)置屬性值
- 如果Bean實(shí)現(xiàn)了BeanNameAware接口纬向,則調(diào)用setBeanName方法,將配置文件中該Bean對(duì)應(yīng)的名稱設(shè)置到Bean中
- 如果Bean實(shí)現(xiàn)了BeanFactory接口戴卜,則調(diào)用setBeanFactory方法逾条,將BeanFactory容器實(shí)例設(shè)置到Bean中
- 如果BeanFactory裝配了BeanPostProcessor后處理器,則將調(diào)用BeanPostProcessor的postProcessBeforeInitialization接口方法對(duì)Bean進(jìn)行加工操作投剥,比如(AOP,動(dòng)態(tài)代理)
- 如果Bean實(shí)現(xiàn)了InitializingBean接口师脂,則將調(diào)用接口的afterPropertiesSet方法
- 如果在<bran>中通過init-method屬性定義了初始化方法,則將執(zhí)行這個(gè)方法
- BeanPostProcessor后處理器定義了兩個(gè)方法:1、postProcessBeforeInitialization
2吃警、postProcessAfterInitialization此時(shí)調(diào)用 - <bean>中指定了Bean的作用范圍是prototype糕篇,則將Bean返回給調(diào)用者,Spring不再管理這個(gè)Bean的生命周期酌心,如果作用范圍是singleton則繼續(xù)對(duì)Bean進(jìn)行管理
- 對(duì)于作用域范圍是singleton的Bean拌消,當(dāng)容器關(guān)閉時(shí),將觸發(fā)Spring對(duì)Bean后續(xù)生命周期的管理工作谒府。如果實(shí)現(xiàn)了DisposanleBean接口則將調(diào)用接口的destory方法
- 對(duì)于作用域是singleton的Bean拼坎,如果<bean>的destory-method屬性指定了Bean的銷毀方法,那么Spring將執(zhí)行Bean的這個(gè)方法完疫,完成Bean資源的釋放等操作
Bean的完整生命周期從實(shí)例化Bean開始泰鸡,到銷毀Bean,其中經(jīng)過了許多關(guān)鍵點(diǎn)壳鹤,這些關(guān)鍵點(diǎn)大致可以分為4類
- Bean自身的方法盛龄,例如構(gòu)造函數(shù)實(shí)例化Bean,屬性設(shè)置方法芳誓,<bean>的init-method和destory-method
- Bean級(jí)生命周期接口方法余舶,比如:BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean
- 容器生命周期接口方法:InstantiationAwareBeanPostProcessor和BeanPostProcessor這兩個(gè)接口實(shí)現(xiàn)的,一般稱它們的實(shí)現(xiàn)類為后處理器
- 工廠后處理器接口方法:AspectJWeavingEnable锹淌、CustomAutowireConfigurer和ConfigurationClassPostProcessor