說明
一、寫作原因
首先解釋一下寫這篇博文的原因,因為在使用spring框架的過程中獲取bean是非常常見的操作,但是網上非常的博文大多承自一家之言,因此很多可操作性上并不強,本文是通過自己實戰,親自嘗試之后提供的幾種方案,供大家一起學習探討。
二、源碼出處
本文提供的測試代碼為chapter-1-springmvc-quickstart中的單元測試類BeanUtilTest如果有需要的可自行下載
https://gitee.com/leo825/spring-framework-learning-example.git
實現方式
本文一共提供七種實現方式:
一.使用BeanFactory直接獲取(不推薦)
使用BeanFactory從工廠中直接獲取Bean實例,但是XmlBeanFactory類已經廢棄,因此不建議使用,測試代碼如下:
/**
* 方式一:XmlBeanFactory已經廢棄不建議使用
*/
@Test
public void getBeanTest1() {
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("ApplicationContext.xml"));
UserInfo userInfo = (UserInfo) beanFactory.getBean("userInfo");
System.out.println(userInfo);
}
二.在初始化時保存ApplicationContext對象
可以在初始化的時候保存ApplicationContext對象,然后通過這個對象獲取Bean,測試代碼如下:
/**
* 方式二:使用ClassPathXmlApplicationContext獲取ApplicationContext
*/
@Test
public void getBeanTest2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfo userInfo = (UserInfo) applicationContext.getBean("userInfo");
System.out.println(userInfo);
}
三.繼承自抽象類ApplicationObjectSupport
可以繼承抽象類ApplicationObjectSupport并將自己繼承的類注入到Spring容器中,示例代碼如下:
/**
* 方法三:繼承ApplicationObjectSupport來獲取ApplicationContext,
* 注意:需要把自己繼承的類注入到Spring
*/
@Test
public void getBeanTest3() {
ApplicationContextUtil2 applicationContextUtil2 = (ApplicationContextUtil2) ApplicationContextUtil.getBean("applicationContextUtil2");
UserInfo userInfo = (UserInfo) applicationContextUtil2.getBean("userInfo");
System.out.println(userInfo);
}
其中ApplicationContextUtil2的代碼如下所示:
public class ApplicationContextUtil2 extends ApplicationObjectSupport {
/**
* 通過bean的id獲取bean對象
* @param beanName
* @return
*/
public Object getBean(String beanName){
return super.getApplicationContext().getBean(beanName);
}
}
最后莫忘了將Bean注入到Spring容器中,通過注解,或者配置均可,本示例通過配置實現
<!-- 測試獲取bean的方式,繼承ApplicationObjectSupport需要先注入這個類 -->
<bean id="applicationContextUtil2" class="com.leo.util.ApplicationContextUtil2"></bean>
四.繼承自抽象類WebApplicationObjectSupport
可以繼承抽象類WebApplicationObjectSupport并將自己繼承的類注入到Spring容器中,示例代碼如下:
/**
* 方法四:繼承WebApplicationObjectSupport來獲取ApplicationContext,
* 注意:需要把自己繼承的類注入到Spring,同時需要添加@WebAppConfiguration注解,否則會找不到web容器
*/
@Test
public void getBeanTest4() {
ApplicationContextUtil3 applicationContextUtil3 = (ApplicationContextUtil3) ApplicationContextUtil.getBean("applicationContextUtil3");
UserInfo userInfo = (UserInfo) applicationContextUtil3.getBean("userInfo");
System.out.println(userInfo);
}
其中ApplicationContextUtil3 示例代碼如下:
public class ApplicationContextUtil3 extends WebApplicationObjectSupport{
/**
* 通過bean的id獲取bean對象
* @param beanName
* @return
*/
public Object getBean(String beanName){
return super.getWebApplicationContext().getBean(beanName);
}
}
最后莫忘了將Bean注入到Spring容器中,通過注解,或者配置均可,本示例通過配置實現
<!-- 測試獲取bean的方式,繼承WebApplicationObjectSupport需要先注入這個類 -->
<bean id="applicationContextUtil3" class="com.leo.util.ApplicationContextUtil3"></bean>
五.使用Spring提供的工具類WebApplicationContextUtils
使用Spring提供的工具類WebApplicationContextUtils來獲取WebApplicationContext對象,這個方法很常見于SpringMVC構建的web項目中,測試代碼如下所示:
/**
* 方法五:使用WebApplicationContextUtils提供的方法獲取ApplicationContext對象
*/
@Test
public void getBeanTest5(){
//模擬ServletContext上下文,不然會出現空指針異常
MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, "/applicationContext.xml");
ServletContextListener listener = new ContextLoaderListener();
ServletContextEvent event = new ServletContextEvent(sc);
listener.contextInitialized(event);
//使用WebApplicationContextUtils的getRequiredWebApplicationContext方法
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
UserInfo userInfo = (UserInfo) webApplicationContext.getBean("userInfo");
System.out.println(userInfo);
//使用WebApplicationContextUtils的getWebApplicationContext方法
WebApplicationContext webApplicationContext2 = WebApplicationContextUtils.getWebApplicationContext(sc);
UserInfo userInfo2 = (UserInfo) webApplicationContext2.getBean("userInfo");
System.out.println(userInfo2);
}
六.實現ApplicationContextAware接口
通過實現ApplicationContextAware接口,在Spring容器啟動的時候將ApplicationContext注入進去,從而獲取ApplicationContext對象,這種方法也是常見的獲取Bean的一種方式,測試代碼如下:
/**
*方法六:實現ApplicationContextAware接口獲取ApplicationContext
*/
@Test
public void getBeanTest6(){
UserInfo userInfo2 = (UserInfo) ApplicationContextUtil.getBean("userInfo");
System.out.println(userInfo2);
}
其中ApplicationContextUtil的實現如下:
public class ApplicationContextUtil implements ApplicationContextAware{
private static ApplicationContext applicationContext;
/**
* 通過bean的id獲取bean對象
* @param beanName
* @return
*/
public static Object getBean(String beanName){
return applicationContext.getBean(beanName);
}
/**
* 根據bean的id和類型獲取bean對象
* @param beanName
* @param clazz
* @param <T>
* @return
*/
public static <T> T getBean(String beanName,Class<T> clazz){
return clazz.cast(getBean(beanName));
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
七.使用ContextLoader提供的getCurrentWebApplicationContext方法
使用ContextLoader提供的getCurrentWebApplicationContext方法提供的方法也是常用的獲取WebApplicationContext的一種方法,這個方法常見于SpringMVC實現的web項目中。
測試代碼如下:
* 方法七:使用ContextLoader的getCurrentWebApplicationContext方法獲取WebApplicationContext
*/
@Test
public void getBeanTest7() {
MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, "/applicationContext.xml");
ServletContextListener listener = new ContextLoaderListener();
ServletContextEvent event = new ServletContextEvent(sc);
listener.contextInitialized(event);
//如果不加上面的模擬創建ServletContext對象,會報空指針異常
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
UserInfo userInfo = (UserInfo) wac.getBean("userInfo");
System.out.println(userInfo);
}