獲取SpringMVC上下文bean例項-SpringContextUtil
專案中,用到了SpringMVC框架。在一個監聽中,需要呼叫server層,並且通過注入的方式,例項化server層。
網上找了很多,提到利用ApplicationContextAware來獲取SpringMVC上下文生成的server層。
例如下:
package com.xsp.onlineshop.web.comm; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * SpringContextUtil * * @author */ @Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; // Spring應用上下文環境 /* * * 實現了ApplicationContextAware 介面,必須實現該方法; * * 通過傳遞applicationContext引數初始化成員變數applicationContext */ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext() { return applicationContext; } @SuppressWarnings("unchecked") public static <T> T getBean(String name) throws BeansException { return (T) applicationContext.getBean(name); } }
但是,在執行的時候,遇到了各種各樣的問題。
現記錄如下:
1,呼叫時,取得的ApplicationContext 為null
ApplicationContext beanFactory= SpringContextUtil.getApplicationContext();
CheckPayTask checkPayTask = beanFactory.getBean(CheckPayTask.class);
執行時,beanFactory為null。原因是SpringContextUtil自身沒有被註冊。
明明<context:component-scan>的路徑裡面包含了SpringContextUtil,怎麼還是取得為null。
在解決這個問題之前,先要弄清楚,Spring上下文和SpringMVC上下文。
先看配置,Spring上下文配置,在Web.xml裡
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:resources/spring.xml</param-value> </context-param> <!-- Spring監聽器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
spring.xml裡面配置的bean屬於Spring上下文。
SpringMVC上下文配置,在Web.xml裡
<!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:resources/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
spring-mvc.xml裡面配置的bean屬於SpringMVC上下文。
注意:SpringMVC上下文和Spring上下文是分開獨立,兩者是父子關係。Spring 父<->SpringMVC 子。但是SpringMVC上下文是可以取得Spring上下文。反之則不行。
在tomcat服務啟動日誌中可以看到,root WebApplicationContext就是Spring的。
再回頭來看,我們的SpringContextUtil,它應該放在Spring裡面來設定,才有效。放在SpringMVC裡面是沒法完成自動例項化的。
問題1,就是由於我把SpringContextUtil的配置放在了spring-mvc.xml了。
問題2,beanFactory不為null,checkPayTask為null。
其實同問題1一樣,既然SpringContextUtil是Spring裡面例項化的bean,從中取得的bean,自然也都是Spring的bean。所以checkPayTask這個bean的設定要放在spring.xml裡面才對。
PS:其實最開始說的“利用ApplicationContextAware來獲取SpringMVC上下文生成的server層”是不對的,應該是利用ApplicationContextAware來獲取Spring上下文生成的server層。