前两天在写这编文章的时候出了N次错,今天还是决定重新把它简单的记录一下。
在 WEB 开发中,可能会很少需要显示的获得 ApplicationContext 来得到由 Spring 进行管理的某些 Bean, 今天我就遇到了,在这里和大家分享一下, WEB 开发中,怎么获取 ApplicationContext
一 要想怎么获取 ApplicationContext, 首先必须明白 Spring 内部 ApplicationContext 是怎样存储的。下面我们来跟踪一下源码
首先:从大家最熟悉的地方开始
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
上面这一段,大家很熟悉吧。好,让我们看一看它到底实现了些啥。
public class ContextLoaderListener implements ServletContextListener {
private ContextLoader contextLoader;
/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
this.contextLoader.initWebApplicationContext(event.getServletContext());
}//下面的略
显然,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化,大家肯定会想,Spring的初始化应该与ServletContext有一定关系吧?有关系吗?接下来让我们进入
ContextLoader.initWebApplicationContext方法
public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
throws IllegalStateException, BeansException {
//从ServletContext中查找,是否存在以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
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为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
//将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key为:Thread.currentThread().getContextClassLoader()即当前线程类加载器
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:
request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")
确实可以,而且我们想到这种方法的时候,Spring早就提供给我们接口了:
public abstract class WebApplicationContextUtils {
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
throws IllegalStateException {
WebApplicationContext wac = getWebApplicationContext(sc);
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
}
return wac;
}
getWebApplicationContext方法如下:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
哈哈,明白了吧,它和我们自己实现的方法是一样的。
现在看一下第二种方法:
前面说到Spring初始化的时候,将ApplicationContext还存了一份到ContextLoader的Map里面,那么我们是不是可以通过Map.get(key) ???很不幸的是,这个Map是私有的。LOOK:
private static final Map currentContextPerThread = CollectionFactory.createConcurrentMapIfPossible(1);
不过,不用担心Spring为我们提供了方法:再LOOK:
public static 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的代码结构如下:
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
就这一个接口。可以这样简单的实现一个ApplicationContextHelper类:
public class ApplicationHelper implements ApplicationContextAware {
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext(){
return this.applicationContext;
}
}
通过ApplicationHelper我们就可以获得咱们想要的AppilcationContext类了
分享到:
相关推荐
但有时候,特别是在多模块项目或者非Web应用中,我们需要一种更加灵活的方式来获取ApplicationContext。 一种常见的做法是实现一个工具类,通过静态方法封装ApplicationContext的获取逻辑。下面是一个简单的示例: ...
在 Web 应用程序中,ApplicationContext 的加载机制是非常重要的, Spring 提供了多种方式来加载 ApplicationContext。 首先,Spring 提供了两种选择来加载 ApplicationContext:ContextLoaderListener 和 ...
本文将深入探讨几种常见的获取Spring容器的方法,包括使用`ApplicationContext`、通过`ServletContext`、利用`ApplicationObjectSupport`、`WebApplicationObjectSupport`以及实现`ApplicationContextAware`接口等。...
当需要在线程中获取Spring注解的bean时,有几种常见的方法: 1. **ThreadLocal**:Spring提供了一种名为`ThreadLocalTargetSource`的特殊`TargetSource`实现,可以将bean实例绑定到当前线程。这样,每个线程都有其...
在Java Web开发领域,Spring框架和Struts框架都是非常重要的技术。Spring框架以其强大的依赖注入(DI)和面向切面编程(AOP)功能,为Java应用提供了轻量级的解决方案。而Struts框架则是一个基于MVC架构模式的Web...
以下将详细阐述Spring与Struts整合的三种方式: 1. **使用Spring的ActionSupport** 这种方式是通过让Struts的Action类继承Spring的`ActionSupport`类,使Action类能够访问Spring的ApplicationContext。首先,在`...
在Java开发中,Spring框架是不可或缺的一部分,它提供了一个强大的依赖注入(DI)和面向切面编程(AOP)的容器。Spring的核心在于其BeanFactory和ApplicationContext,它们使得对象的管理和装配变得简单。这里我们将...
在Java Web开发中,Spring框架提供了强大的依赖注入和管理组件的能力。当我们在Servlet环境中工作时,有时需要在Servlet中直接访问由Spring管理的Bean,以便利用Spring提供的服务和功能。以下是如何在Servlet中直接...
这种方式通常用于 Web 应用程序中,因为它可以从 ServletContext 中获取 ApplicationContext。 例如,我们可以在 web.xml 文件中定义一个 listener,如下所示: ```xml <listener-class>org.springframework.web...
Spring提供了`ContextLoader`和`WebApplicationContextUtils`等工具类,可以从当前线程或ServletContext中获取ApplicationContext。 ```java // 在非Web应用中 ApplicationContext ac = ContextLoader....
在IT行业中,SpringMVC、Spring和Mybatis是三大核心框架,它们的集成使用是Java Web开发中的常见实践。这个集成开发环境旨在提供一个高效、灵活的开发平台,以实现业务逻辑与数据访问的分离,提高代码的可维护性和可...
此外,在实际开发中还可能遇到其他获取Bean的方式,比如使用`ApplicationContext`的子类如`ClassPathXmlApplicationContext`或`FileSystemXmlApplicationContext`等。选择哪种方式取决于具体的应用场景和个人喜好。...
在Eclipse中创建一个基于Spring的Web应用涉及多个步骤,主要涵盖了Spring框架的Web模块、ApplicationContext的使用以及在Web容器中的配置。以下是详细的过程和相关知识点: 1. **Spring Web模块**: Spring框架...
这个问题在实际开发中非常常见,特别是在异步线程或某些特殊情况下无法使用AutoWired和Component注解时,就需要使用ApplicationContext来获取bean。 首先,我们需要了解什么是ApplicationContext。...
在开发Web应用时,Spring框架和Web服务器的配合使用是至关重要的。本实例将深入探讨如何利用Spring框架与Web服务器(如...通过这个实例,你可以掌握Spring与Web服务器协作开发的完整流程,进一步提升你的Web开发技能。
Struts 与 Spring 的整合是Java Web开发中常见的需求,因为这两个框架分别在MVC模式和依赖注入(DI)及面向切面编程(AOP)方面提供了强大的功能。本文主要介绍了三种整合Struts应用程序与Spring的方法。 首先,Spring...
在IT行业中,Spring、iBATIS和Struts1是经典的Java Web开发框架,它们的集成应用为开发者提供了灵活且强大的后端服务构建能力。本文将深入探讨这些技术的结合使用,以及它们如何协同工作来创建高效的应用程序。 ...
在Spring框架的开发中,涉及了多个...以上就是标题和描述中提到的关键知识点,它们构成了Spring开发的基础,并且在实际的Java Web项目中扮演着重要角色。了解和掌握这些概念,对于成为一名熟练的Spring开发者至关重要。
总结,Mybatis与Spring的整合创建Web项目,是现代Java Web开发中的常见实践,它能够提高开发效率,降低维护成本。理解并熟练掌握这种整合方式,对于提升开发者在企业级应用开发中的技能至关重要。