在spring中我们经常需要获取ROOT ApplicationContext, 以下就几种获取方式作分析:
在使用spring的web项目中,在web.xml中有如下配置,进行spring的初始化:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
进入该ContextLoaderListener,注意以下代码:
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
ContextLoaderListener在实现ServletContextListener接口的同时,也继承了ContextLoader,initWebApplicationContext是在ContextLoader中定义的,我们注意以下代码片段:
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
很明显,在context创建后,同时也保存到了servletContext中,因此这里有了第一种获取方式:
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
该方法的原理如下:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {
····省略代码·····
Object attr = sc.getAttribute(attrName);
····省略代码·····
return (WebApplicationContext) attr;
}
当不能够传入ServletContext时,怎么获取ApplicationContext呢,spring为我们提供了ApplicationContextAware接口,实现该接口的bean即可获得ApplicationContext对象。需要注意的是,该bean一定要在spring中定义过,是spring管理的bean,spring在初始化该bean的时候,会进行赋值。
第二种获取方式:
@Service
public class SysScheduleJobService implements ApplicationContextAware{
private static Logger logger = LoggerFactory
.getLogger(SysScheduleJobService.class);
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
// TODO Auto-generated method stub
this.applicationContext = applicationContext;
}
}
另外,在使用springMVC的时候,需要获得springMVC 的 ApplicationContext有如下方式:
ApplicationContext ctx = RequestContextUtils
.findWebApplicationContext(request);
该方法代码实现如下:
public static WebApplicationContext findWebApplicationContext(HttpServletRequest request) {
return findWebApplicationContext(request, request.getServletContext());
}
public static WebApplicationContext findWebApplicationContext(
HttpServletRequest request, ServletContext servletContext) {
WebApplicationContext webApplicationContext = (WebApplicationContext) request.getAttribute(
DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (webApplicationContext == null) {
if (servletContext != null) {
webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
if (webApplicationContext == null) {
webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
}
}
return webApplicationContext;
}
这里获取的就是DispatcherServlet ApplicationContext 。DispatcherServlet ApplicationContext 的双亲为ROOT ApplicationContext ,则可以在DispatcherServlet ApplicationContext中获取ROOT ApplicationContext中定义的bean,而在ROOT ApplicationContext无法获取DispatcherServlet ApplicationContext中定义的bean。