Web开发中获取Spring的ApplicationContext的三种方式

在 WEB 开发中,可能会很少需要显示的获得 ApplicationContext 来得到由 Spring 进行管理的某些 Bean, 今天我就遇到了,在这里和大家分享一下, WEB 开发中,怎么获取 ApplicationContext 

一       要想怎么获取 ApplicationContext, 首先必须明白 Spring 内部 ApplicationContext 是怎样存储的。下面我们来跟踪一下源码 

首先:从大家最熟悉的地方开始 

  1. <listener>  
  2.      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  3.   </listener>  

 上面这一段,大家很熟悉吧。好,让我们看一看它到底实现了些啥。

  

Java代码 
  1. public class ContextLoaderListener<span style="color: #ff0000;"> <span style="color: #000000;">implements ServletContextListener</span></span> {  
  2.   
  3.     private ContextLoader contextLoader;  
  4.   
  5.     /** 
  6.      * Initialize the root web application context.                                      
  7.      */   
  8.     public void <span style="color: #000000;">contextInitialized</span>(ServletContextEvent event) {  
  9.         this.contextLoader = createContextLoader();  
  10.         this.contextLoader.<span style="color: #000000;">initWebApplicationContext</span>(event.getServletContext());  
  11.     }//下面的略  

 
显然,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化,大家肯定会想,Spring的初始化应该与ServletContext有一定关系吧?有关系吗?接下来让我们进入

ContextLoader.initWebApplicationContext方法

 

 

Java代码
  1. public WebApplicationContext initWebApplicationContext(ServletContext servletContext)  
  2.             throws IllegalStateException, BeansException {  
  3.   
  4.         //从ServletContext中查找,是否存在以<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值</span>  
Java代码
  1. 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> {  
  2.     throw new IllegalStateException(  
  3.             "Cannot initialize context because there is already a root application context present - " +  
  4.             "check whether you have multiple ContextLoader* definitions in your web.xml!");  
  5. }  
  6.   
  7.           
  8. try {  
  9.     // Determine parent for root web application context, if any.  
  10.     ApplicationContext parent = loadParentContext(servletContext);  
  11.   
  12.     // it is available on ServletContext shutdown.  
  13.     this.context = createWebApplicationContext(servletContext, parent);  
  14.     //将ApplicationContext放入ServletContext中,其key为<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE</span>  
Java代码
  1. <span style="color: #000000;">          <span>servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);</span></span>  
  2.             //将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key为:<span style="color: #000000;">Thread.currentThread().getContextClassLoader()即当前线程类加载器</span>  
Java代码
  1.     currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);  
  2.   
  3.     return this.context;  
  4. }  

 从上面的代码大家应该明白了Spring初始化之后,将ApplicationContext存到在了两个地方,那么是不是意味着我们可以通过两种方式取得ApplicationContext?

 

第一种获取方式:


 注意:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

即为 "org.springframework.web.context.WebApplicationContext.ROOT"

 

那么咱们是不是可以这样获得ApplicationContext:

  

Java代码
  1. request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")  

 确实可以,而且我们想到这种方法的时候,Spring早就提供给我们接口了:

 

Java代码
  1. public abstract class WebApplicationContextUtils {  
  2.       
  3.            
  4. public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)  
  5.         throws IllegalStateException {  
  6.   
  7.         <span style="color: #000000;">WebApplicationContext wac = getWebApplicationContext(sc);</span>  
  8.         if (wac == null) {  
  9.             throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");  
  10.         }  
  11.         return wac;  
  12.     }  

 getWebApplicationContext方法如下:

 

 

Java代码
  1. public static WebApplicationContext getWebApplicationContext(ServletContext sc) {  
  2.         return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);  
  3.     }  

 哈哈,明白了吧,它和我们自己实现的方法是一样的。

 

现在看一下第二种方法:

 

前面说到Spring初始化的时候,将ApplicationContext还存了一份到ContextLoader的Map里面,那么我们是不是可以通过Map.get(key)  ???很不幸的是,这个Map是私有的。LOOK:

 

Java代码
  1. <span style="color: #000000;">private</span> static final Map currentContextPerThread = CollectionFactory.createConcurrentMapIfPossible(1);  

 

不过,不用担心Spring为我们提供了方法:再LOOK:

 

Java代码
  1. <span style="color: #000000;">public static</span> WebApplicationContext getCurrentWebApplicationContext() {  
  2.         return (WebApplicationContext) currentContextPerThread.get(Thread.currentThread().getContextClassLoader());  
  3.     }  

 

这下我们放心了吧!哈哈,第二种方法也搞定了。第二种方法与第一种方法相比有什么好的地方呢?就是它不需要参数,只要在Web容器中,当Spring初始化之后,你不需要传入任何参数,就可以获得ApplicationContext为咱们服务。是不是很好?不过作者在用这个方法的时候,发现在Spring2.52版本中是不存在的,但是在2.5.5版本中提供了!!

 

其实第二种获取方法看上去简单,但他的原理还是有一定难度的,他与类加载器的线程上下文相关,有不知道大家有没有听说过,这个线程上下文在咱们常用的Mysql驱动中有用到,下次可以和大家一起分享一下。

 

第三种方式:借用ApplicationContextAware,ApplicationContext的帮助类能够自动装载ApplicationContext,只要你将某个类实现这个接口,并将这个实现类在Spring配置文件中进行配置,Spring会自动帮你进行注

入 ApplicationContext.ApplicationContextAware的代码结构如下:

 

 

Java代码
  1. public interface ApplicationContextAware {  
  2.       
  3.         void setApplicationContext(ApplicationContext applicationContext) throws BeansException;  
  4.   
  5. }  

 

就这一个接口。可以这样简单的实现一个ApplicationContextHelper类:

 

 

 

 

Java代码
  1. public class ApplicationHelper implements ApplicationContextAware {  
  2.   
  3.       
  4.     <span style="color: #000000;">private ApplicationContext applicationContext;</span>  
  5.       
  6.     public void setApplicationContext(ApplicationContext applicationContext)  
  7.             throws BeansException {  
  8.             this.applicationContext = applicationContext;  
  9.     }  
  10.   
  11.       
  12.     public  ApplicationContext<span style="color: #000000;"> <span>getApplicationContext(){</span></span>  
  13.         return this.applicationContext;  
  14.     }  
  15. }  

 

通过ApplicationHelper我们就可以获得咱们想要的AppilcationContext类了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值