所謂的ioc容器,以我目前狹義的理解挪蹭,即指ApplicationContext類(lèi)亭饵,在spring全家桶中也被稱(chēng)為上下文。
我們一直在說(shuō)梁厉,spring是一個(gè)解耦合的框架辜羊,spring通過(guò)xml或注解依賴(lài)注入相關(guān)的bean,不需要手動(dòng)的new對(duì)象词顾。但究竟是怎么注入的還是沒(méi)有清晰的概念八秃。這篇博客在考察相關(guān)資料之后完成。
引入問(wèn)題:
想一想肉盹,在我們一開(kāi)始學(xué)習(xí)spring的時(shí)候昔驱,我們寫(xiě)了幾個(gè)bean,然后在xml中做配置上忍,然后怎么測(cè)試依賴(lài)注入的呢骤肛?
是像springboot中那樣直接@Autowired嗎?
如果還有印象窍蓝,那么大多數(shù)人的起點(diǎn)應(yīng)該是這段代碼:
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
ClassName cn = (ClassName)ac.getBean("beanName");
通過(guò)ClassPathXmlApplicationContext來(lái)加載我們寫(xiě)好的spring配置文件腋颠,用ApplicationContext來(lái)接收,隨后使用getBean方法來(lái)得到我們?cè)趚ml中配置好的bean吓笙。
而ApplicationContext就是ioc容器淑玫,所有的bean都將被它所管理,支配面睛。
深入研究
Spring有兩個(gè)核心接口:BeanFactory和ApplicationContext絮蒿,其中ApplicationContext是BeanFactory的子接口。他們都可代表Spring容器侮穿,Spring容器是生成Bean實(shí)例的工廠歌径,并且管理容器中的Bean。
Bean是Spring管理的基本單位亲茅,在基于Spring的Java EE應(yīng)用中,所有的組件都被當(dāng)成Bean處理,除了自定義的javabean克锣,還包括數(shù)據(jù)源茵肃、事務(wù)管理器等衣迷。在Spring中栋操,Bean的是一個(gè)非常廣義的概念撵术,任何的Java對(duì)象抖甘、Java組件都被當(dāng)成Bean處理搞莺。
而且應(yīng)用中的所有組件主穗,都處于Spring的管理下温算,都被Spring以Bean的方式管理扣草,Spring負(fù)責(zé)創(chuàng)建Bean實(shí)例胆绊,并管理他們的生命周期氨鹏。Bean在Spring容器中運(yùn)行,無(wú)須感受Spring容器的存在压状,一樣可以接受Spring的依賴(lài)注入仆抵,包括Bean屬性的注入,協(xié)作者的注入种冬、依賴(lài)關(guān)系的注入等镣丑。
Spring容器負(fù)責(zé)創(chuàng)建Bean實(shí)例,所以需要知道每個(gè)Bean的實(shí)現(xiàn)類(lèi)娱两,Java程序面向接口編程莺匠,無(wú)須關(guān)心Bean實(shí)例的實(shí)現(xiàn)類(lèi);但是Spring容器必須能夠精確知道每個(gè)Bean實(shí)例的實(shí)現(xiàn)類(lèi)十兢,因此Spring配置文件必須精確配置Bean實(shí)例的實(shí)現(xiàn)類(lèi)趣竣。
基本的Spring容器
Spring容器最基本的接口就是BeanFactory。BeanFactory負(fù)責(zé)配置纪挎、創(chuàng)建期贫、管理Bean,他有一個(gè)子接口:ApplicationContext异袄,因此也稱(chēng)之為Spring上下文通砍。Spring容器負(fù)責(zé)管理Bean與Bean之間的依賴(lài)關(guān)系。
BeanFactory接口包含以下幾個(gè)基本方法:
? Boolean containBean(String name):判斷Spring容器是否包含id為name的Bean實(shí)例烤蜕。
? <T> getBean(Class<T> requiredTypr):獲取Spring容器中屬于requiredType類(lèi)型的唯一的Bean實(shí)例封孙。
? Object getBean(String name):返回Sprin容器中id為name的Bean實(shí)例。
? <T> T getBean(String name,Class requiredType):返回容器中id為name,并且類(lèi)型為requiredType的Bean
? Class <?> getType(String name):返回容器中指定Bean實(shí)例的類(lèi)型讽营。
調(diào)用者只需使用getBean()方法即可獲得指定Bean的引用虎忌,無(wú)須關(guān)心Bean的實(shí)例化過(guò)程。即Bean實(shí)例的創(chuàng)建過(guò)程完全透明橱鹏。
在使用BeanFactory接口時(shí)膜蠢,我們一般都是使用這個(gè)實(shí)現(xiàn)類(lèi):org.springframework.beans.factory.xml.XmlBeanFactory堪藐。然而ApplicationContext作為BeanFactory的子接口,使用它作為Spring容器會(huì)更加方便挑围。它的實(shí)現(xiàn)類(lèi)有:FileSystemXmlApplicationContext礁竞、ClassPathXmlApplicationContext、AnnotationConfigApplicationContext杉辙。
創(chuàng)建Spring容器實(shí)例時(shí)模捂,必須提供Spring容器管理的Bean的詳細(xì)配置信息。Spring的配置信息通常采用xml配置文件來(lái)設(shè)置蜘矢,因此狂男,創(chuàng)建BeanFactory實(shí)例時(shí),應(yīng)該提供XML配置文件作為參數(shù)品腹。
XML配置文件通常使用Resource對(duì)象傳入岖食。Resource接口是Spring提供的資源訪問(wèn)接口,通過(guò)使用該接口珍昨,Spring能夠以簡(jiǎn)單县耽、透明的方式訪問(wèn)磁盤(pán)、類(lèi)路徑以及網(wǎng)絡(luò)上的資源镣典。
FileSystemXmlApplicationContext:以基于文件系統(tǒng)的XML配置文件創(chuàng)建ApplicationContext實(shí)例兔毙。
ClassPathXmlApplicationContext:以類(lèi)加載路徑下的XML配置文件創(chuàng)建的ApplicationContext實(shí)例。
//搜索CLASSPATH路徑兄春,以classpath路徑下的bean.xml澎剥、service.xml文件創(chuàng)建applicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"bean.xml","service.xml"});
//以指定路徑下的bean.xml、service.xml文件創(chuàng)建applicationContext
ApplicationContext ctx1 = new FileSystemXmlApplicationContext(new String[]{"bean.xml","service.xml"});
ps:
在Spring中我們可以使用Spring容器中g(shù)etBean()方法來(lái)獲取Spring容器中的Bean實(shí)例赶舆。在這樣的訪問(wèn)模式下哑姚,程序中總是持有Spring容器的引用。(即我們想得到ioc中的bean至少要在程序中創(chuàng)建一個(gè)applicationContext類(lèi))但是在實(shí)際的應(yīng)用中芜茵,一般是采用像springmvc.xml中自動(dòng)掃描包+@Autowired的方式來(lái)自動(dòng)注入叙量。
而到了springboot,由于xxx-autoconfigration類(lèi)的存在九串,我們連springmvc.xml這種配置文件都省了绞佩,如果需要將某些類(lèi)加入ioc容器,只需要加上相關(guān)注解猪钮,如@controller品山,@service,@bean等烤低。
在使用的時(shí)候肘交,也只需要@Autowired,對(duì)于使用者來(lái)說(shuō)完全沒(méi)有任何門(mén)檻扑馁。