SSH框架(一) Web开发中获取Spring的ApplicationContext的三种方式
2014-08-20 13:52
483 查看
在 WEB 开发中,可能会很少需要显示的获得 ApplicationContext 来得到由 Spring 进行管理的某些 Bean, 今天我就遇到了,在这里和大家分享一下, WEB 开发中,怎么获取 ApplicationContext
一 要想怎么获取 ApplicationContext, 首先必须明白 Spring 内部 ApplicationContext 是怎样存储的。下面我们来跟踪一下源码
首先:从大家最熟悉的地方开始
Java代码
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
上面这一段,大家很熟悉吧。好,让我们看一看它到底实现了些啥。
Java代码
public class ContextLoaderListener<span style="color: #ff0000;"> <span style="color: #000000;">implements ServletContextListener</span></span> {
private ContextLoader contextLoader;
/**
* Initialize the root web application context.
*/
public void <span style="color: #000000;">contextInitialized</span>(ServletContextEvent event) {
this.contextLoader = createContextLoader();
this.contextLoader.<span style="color: #000000;">initWebApplicationContext</span>(event.getServletContext());
}//下面的略
显然,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化,大家肯定会想,Spring的初始化应该与ServletContext有一定关系吧?有关系吗?接下来让我们进入
ContextLoader.initWebApplicationContext方法
Java代码
public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
throws IllegalStateException, BeansException {
//从ServletContext中查找,是否存在以<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值</span>
Java代码
if (<span style="color: #ff0000;"><span style="color: #000000;">servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null</span><span style="color: #000000;">)</span></span> {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
try {
// Determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
// it is available on ServletContext shutdown.
this.context = createWebApplicationContext(servletContext, parent);
//将ApplicationContext放入ServletContext中,其key为<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE</span>
Java代码
<span style="color: #000000;"> <span>servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);</span></span>
//将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key为:<span style="color: #000000;">Thread.currentThread().getContextClassLoader()即当前线程类加载器</span>
Java代码
currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
return this.context;
}
从上面的代码大家应该明白了Spring初始化之后,将ApplicationContext存到在了两个地方,那么是不是意味着我们可以通过两种方式取得ApplicationContext?
第一种获取方式:
注意:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
即为 "org.springframework.web.context.WebApplicationContext.ROOT"
那么咱们是不是可以这样获得ApplicationContext:
Java代码
request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")
确实可以,而且我们想到这种方法的时候,Spring早就提供给我们接口了:
Java代码
public abstract class WebApplicationContextUtils {
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
throws IllegalStateException {
<span style="color: #000000;">WebApplicationContext wac = getWebApplicationContext(sc);</span>
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
}
return wac;
}
getWebApplicationContext方法如下:
Java代码
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
哈哈,明白了吧,它和我们自己实现的方法是一样的。
现在看一下第二种方法:
前面说到Spring初始化的时候,将ApplicationContext还存了一份到ContextLoader的Map里面,那么我们是不是可以通过Map.get(key) ???很不幸的是,这个Map是私有的。LOOK:
Java代码
<span style="color: #000000;">private</span> static final Map currentContextPerThread = CollectionFactory.createConcurrentMapIfPossible(1);
不过,不用担心Spring为我们提供了方法:再LOOK:
Java代码
<span style="color: #000000;">public static</span> WebApplicationContext getCurrentWebApplicationContext() {
return (WebApplicationContext) currentContextPerThread.get(Thread.currentThread().getContextClassLoader());
}
这下我们放心了吧!哈哈,第二种方法也搞定了。第二种方法与第一种方法相比有什么好的地方呢?就是它不需要参数,只要在Web容器中,当Spring初始化之后,你不需要传入任何参数,就可以获得ApplicationContext为咱们服务。是不是很好?不过作者在用这个方法的时候,发现在Spring2.52版本中是不存在的,但是在2.5.5版本中提供了!!
其实第二种获取方法看上去简单,但他的原理还是有一定难度的,他与类加载器的线程上下文相关,有不知道大家有没有听说过,这个线程上下文在咱们常用的Mysql驱动中有用到,下次可以和大家一起分享一下。
第三种方式:借用ApplicationContextAware,ApplicationContext的帮助类能够
Java代码
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
就这一个接口。可以这样简单的实现一个ApplicationContextHelper类:
Java代码
public class ApplicationHelper implements ApplicationContextAware {
<span style="color: #000000;">private ApplicationContext applicationContext;</span>
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext<span style="color: #000000;"> <span>getApplicationContext(){</span></span>
return this.applicationContext;
}
}
通过ApplicationHelper我们就可以获得咱们想要的AppilcationContext类了
一 要想怎么获取 ApplicationContext, 首先必须明白 Spring 内部 ApplicationContext 是怎样存储的。下面我们来跟踪一下源码
首先:从大家最熟悉的地方开始
Java代码
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
上面这一段,大家很熟悉吧。好,让我们看一看它到底实现了些啥。
Java代码
public class ContextLoaderListener<span style="color: #ff0000;"> <span style="color: #000000;">implements ServletContextListener</span></span> {
private ContextLoader contextLoader;
/**
* Initialize the root web application context.
*/
public void <span style="color: #000000;">contextInitialized</span>(ServletContextEvent event) {
this.contextLoader = createContextLoader();
this.contextLoader.<span style="color: #000000;">initWebApplicationContext</span>(event.getServletContext());
}//下面的略
显然,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化,大家肯定会想,Spring的初始化应该与ServletContext有一定关系吧?有关系吗?接下来让我们进入
ContextLoader.initWebApplicationContext方法
Java代码
public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
throws IllegalStateException, BeansException {
//从ServletContext中查找,是否存在以<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值</span>
Java代码
if (<span style="color: #ff0000;"><span style="color: #000000;">servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null</span><span style="color: #000000;">)</span></span> {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
try {
// Determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
// it is available on ServletContext shutdown.
this.context = createWebApplicationContext(servletContext, parent);
//将ApplicationContext放入ServletContext中,其key为<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE</span>
Java代码
<span style="color: #000000;"> <span>servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);</span></span>
//将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key为:<span style="color: #000000;">Thread.currentThread().getContextClassLoader()即当前线程类加载器</span>
Java代码
currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
return this.context;
}
从上面的代码大家应该明白了Spring初始化之后,将ApplicationContext存到在了两个地方,那么是不是意味着我们可以通过两种方式取得ApplicationContext?
第一种获取方式:
注意:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
即为 "org.springframework.web.context.WebApplicationContext.ROOT"
那么咱们是不是可以这样获得ApplicationContext:
Java代码
request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")
确实可以,而且我们想到这种方法的时候,Spring早就提供给我们接口了:
Java代码
public abstract class WebApplicationContextUtils {
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
throws IllegalStateException {
<span style="color: #000000;">WebApplicationContext wac = getWebApplicationContext(sc);</span>
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
}
return wac;
}
getWebApplicationContext方法如下:
Java代码
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
哈哈,明白了吧,它和我们自己实现的方法是一样的。
现在看一下第二种方法:
前面说到Spring初始化的时候,将ApplicationContext还存了一份到ContextLoader的Map里面,那么我们是不是可以通过Map.get(key) ???很不幸的是,这个Map是私有的。LOOK:
Java代码
<span style="color: #000000;">private</span> static final Map currentContextPerThread = CollectionFactory.createConcurrentMapIfPossible(1);
不过,不用担心Spring为我们提供了方法:再LOOK:
Java代码
<span style="color: #000000;">public static</span> WebApplicationContext getCurrentWebApplicationContext() {
return (WebApplicationContext) currentContextPerThread.get(Thread.currentThread().getContextClassLoader());
}
这下我们放心了吧!哈哈,第二种方法也搞定了。第二种方法与第一种方法相比有什么好的地方呢?就是它不需要参数,只要在Web容器中,当Spring初始化之后,你不需要传入任何参数,就可以获得ApplicationContext为咱们服务。是不是很好?不过作者在用这个方法的时候,发现在Spring2.52版本中是不存在的,但是在2.5.5版本中提供了!!
其实第二种获取方法看上去简单,但他的原理还是有一定难度的,他与类加载器的线程上下文相关,有不知道大家有没有听说过,这个线程上下文在咱们常用的Mysql驱动中有用到,下次可以和大家一起分享一下。
第三种方式:借用ApplicationContextAware,ApplicationContext的帮助类能够
自动装载ApplicationContext,只要你将某个类实现这个接口,并将这个实现类在Spring配置文件中进行配置,Spring会自动帮你进行注
入 ApplicationContext.ApplicationContextAware的代码结构如下:
Java代码
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
就这一个接口。可以这样简单的实现一个ApplicationContextHelper类:
Java代码
public class ApplicationHelper implements ApplicationContextAware {
<span style="color: #000000;">private ApplicationContext applicationContext;</span>
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext<span style="color: #000000;"> <span>getApplicationContext(){</span></span>
return this.applicationContext;
}
}
通过ApplicationHelper我们就可以获得咱们想要的AppilcationContext类了
相关文章推荐
- Web开发中获取Spring的ApplicationContext的三种方式
- Web开发中获取Spring的ApplicationContext的三种方式
- Web开发中获取Spring的ApplicationContext的几种方式
- Spring获取bean的三种方式
- 在webForm中WebRequest/WebClient/WebBrowser获取远程页面源码的三种方式(downmoon)
- JAVAWEB开发之Spring详解之——Spring的入门以及IOC容器装配Bean(xml和注解的方式)、Spring整合web开发、整合Junit4测试
- Android三种Webview获取Javascript返回值/属性方式
- python web应用开发中获取各种参数的方式
- 在webForm中WebRequest\WebClient\WebBrowser获取远程页面源码的三种方式(downmoon)
- ios开发webview 的三种引用方式以及动态更新本地静态页的方法
- Freemarker和Spring开发:获取相对路劲和绝对路径的最优方式
- 在webForm中WebRequest\WebClient\WebBrowser获取远程页面源码的三种方式(downmoon)
- java webservice服务器端获取request对象的三种方式
- 基于Struts、Spring、Hibernate的JavaWeb开发SSH框架配置
- 【spring Boot】spring boot获取资源文件的三种方式【两种情况下】
- 【Spring】web开发 javaConfig方式 图解
- web.xml中配置spring的几种方式 以及 Spring获取Bean的几种方式
- web.xml中配置spring的几种方式 以及 Spring获取Bean的几种方式
- web.xml中配置spring的几种方式 以及 Spring获取Bean的几种方式
- 使用web.xml方式加载Spring时,获取Spring context的两种方式