Spring是一個(gè)輕量級(jí)的控制反轉(zhuǎn)(IoC)和面向切面(AOP)的容器框架,如何在程序中獲取Spring配置的bean呢?
Bean工廠(com.springframework.beans.factory.BeanFactory)是Spring框架最核心的接口,它提供了高級(jí)IoC的配置機(jī)制。BeanFactory使管理不同類型的Java對(duì)象成為可能,應(yīng)用上下文(com.springframework.context.ApplicationContext)建立在BeanFactory基礎(chǔ)之上,提供了更多面向應(yīng)用的功能,它提供了國(guó)際化支持和框架事件體系,更易于創(chuàng)建實(shí)際應(yīng)用。我們一般稱BeanFactory為IoC容器,而稱ApplicationContext為應(yīng)用上下文。但有時(shí)為了行文方便,我們也將ApplicationContext稱為Spring容器。
對(duì)于兩者的用途,我們可以進(jìn)行簡(jiǎn)單劃分:BeanFactory是Spring框架的基礎(chǔ)設(shè)施,面向Spring本身;ApplicationContext面向使用Spring框架的開(kāi)發(fā)者,幾乎所有的應(yīng)用場(chǎng)合我們都直接使用ApplicationContext而非底層的BeanFactory。
ApplicationContext的初始化和BeanFactory有一個(gè)重大的區(qū)別:BeanFactory在初始化容器時(shí),并未實(shí)例化Bean,直到第一次訪問(wèn)某個(gè)Bean時(shí)才實(shí)例目標(biāo)Bean;而ApplicationContext則在初始化應(yīng)用上下文時(shí)就實(shí)例化所有單實(shí)例的Bean。因此ApplicationContext的初始化時(shí)間會(huì)比BeanFactory稍長(zhǎng)一些
本文不涉及通過(guò) @Resource 、 @Autowired 自動(dòng)注入,僅僅通過(guò) ApplicationContext 獲取 Sping 配置文件中的 Bean 。
要獲取XML中配置的Bean,最關(guān)鍵的是獲取org.springframework.context.ApplicationContext
第一種獲取 ApplicationContext 的方法:
1
2
3
|
import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; ApplicationContext applicationContext = new FileSystemXmlApplicationContext( "applicationContext.xml" ); |
或者
1
2
3
|
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; private ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "applicationContext.xml" ); |
這種方式實(shí)例化applicationContext是非常耗時(shí)的,這種方式適用于采用Spring框架的獨(dú)立應(yīng)用程序,僅僅推薦使用在程序需要通過(guò)配置文件手工初始化Spring的情況。ApplicationContext的主要實(shí)現(xiàn)類是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,前者默認(rèn)從類路徑加載配置文件,后者默認(rèn)從文件系統(tǒng)中裝載配置文件
例子:
1
2
3
4
5
6
|
public class BeanManager { private static ApplicationContext context = new ClassPathXmlApplicationContext( "appcontext.xml" ) ; public static Object getBean(String beanId) { return context.getBean(beanId); } } |
在 web.xml 中寫(xiě)一個(gè) servlet ,自動(dòng)啟動(dòng), init 方法中調(diào)用一下 BeanManager
1
2
3
4
|
init() throws ServletException { BeanManager bm = new BeanManager(); //可選的,為的是在 web 應(yīng)用啟動(dòng)的時(shí)候就讓 spring 加載 bean 配置。 // 否則會(huì)在第一次調(diào)用 BeanManager 的時(shí)候加載,影響一次速度。 } |
在 java 代碼中使用 BeanManager.getBean(String beanId); 來(lái)獲得 bean 實(shí)例。
第二種獲取 ApplicationContext 的方法: 通過(guò)Spring提供的工具類獲取ApplicationContext對(duì)象,專為web工程定制的方法,推薦Web項(xiàng)目中使用。例如:
1
2
3
4
5
|
ServletContext servletContext = request.getSession().getServletContext(); ApplicationContext ac1 = WebApplicationContextUtils .getRequiredWebApplicationContext(ServletContext sc) ApplicationContext ac2 = WebApplicationContextUtils .getWebApplicationContext(ServletContext sc) ac1.getBean( "beanId" ); ac2.getBean( "beanId" ); |
通過(guò)javax.servlet.ServletContext 獲取到ApplicationContext實(shí)例對(duì)象,這意味著,必須使用到request、session等等。
這樣,就不能把ApplicationContext對(duì)象設(shè)置為成員變量。需要在每個(gè)具體的方法中通過(guò)request、session等獲取到ServletContext再獲取ApplicationContext實(shí)例。
因此,此方法僅僅推薦使用在可以獲取到ServletContext對(duì)象的Web項(xiàng)目中,并且不需要將ApplicationContext對(duì)象定義為成員變量的情況下。
注意:當(dāng)使用WebApplicationContextUtils獲取ApplicationContext實(shí)例時(shí),需要在web.xml配置文件中添加org.springframework.web.context.ContextLoaderListener監(jiān)聽(tīng)器,否則獲取不到ApplicationContext對(duì)象,返回Null。
配置文件:web.xml
1
2
3
4
5
6
7
8
9
10
|
<!--ContextLoaderListener自動(dòng)注入 applicationContext,通過(guò) WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext())獲取 --> <!--Spring配置文件加載位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appContext.xml,/WEB-INF/spring/appInterceptor.xml</param-value> </context-param> <listener> <listener- class >org.springframework.web.context.ContextLoaderListener</listener- class > </listener> |
3. 繼承自抽象類ApplicationObjectSupport
抽象類ApplicationObjectSupport提供getApplicationContext()方法,可以方便的獲取到ApplicationContext。Spring初始化時(shí),會(huì)通過(guò)該抽象類的setApplicationContext(ApplicationContext context)方法將ApplicationContext 對(duì)象注入。
4. 繼承自抽象類WebApplicationObjectSupport
通過(guò)繼承org.springframework.web.context.support.WebApplicationObjectSupport使用getWebApplicationContext() 獲取到org.springframework.web.context.WebApplicationContext由于Web應(yīng)用比一般的應(yīng)用擁有更多的特性,因此WebApplicationContext擴(kuò)展了ApplicationContext。WebApplicationContext定義了一個(gè)常量ROOT_WEB_APPLICATION_ CONTEXT_ATTRIBUTE,在上下文啟動(dòng)時(shí),WebApplicationContext實(shí)例即以此為鍵放置在ServletContext的屬性列表中,因此我們可以直接通過(guò)以下語(yǔ)句從Web容器中獲取WebApplicationContext:
1
2
|
WebApplicationContext wac = (WebApplicationContext)servletContext.getAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); |
5. 實(shí)現(xiàn)接口ApplicationContextAware
實(shí)現(xiàn)該接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 對(duì)象。Spring初始化時(shí),會(huì)通過(guò)該方法將ApplicationContext 對(duì)象注入。
第三、四、五種方法都需要將類配置在 Spring 配置文件中:
1
2
|
<!--假定ApplicationContextTool為繼承或者實(shí)現(xiàn)了第三、四、五種方法的具體實(shí)現(xiàn)類--> <bean class = "com.twovv.utils.ApplicationContextTool" ></bean> |
否則將獲取不到 ApplicationContext ,返回 Null 。
以上內(nèi)容給大家介紹了Java中Spring獲取bean方法小結(jié),希望大家喜歡。