`
dxm1986
  • 浏览: 435191 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多

前两天在写这编文章的时候出了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类了

 

 

7
2
分享到:
评论
5 楼 雪之痕 2012-12-06  
嗯,楼主写的不错,受教了!
4 楼 dxm1986 2010-09-20  
PS:
org.springframework.web.servlet.FrameworkServlet.CONTEXT.dis 其中dis为DispatcherServlet在web.xml中的配置名字。

String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);

public String getServletContextAttributeName() {
    return SERVLET_CONTEXT_PREFIX + getServletName();
}

public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";

public final String getServletName() {
return (getServletConfig() != null ? getServletConfig().getServletName() : null);
}
3 楼 dxm1986 2010-09-20  
zywang 写道
你找找用Struts集成Spring的时候wac被保存到什么地方去的吧,貌似不是org.springframework.web.context.WebApplicationContext.ROOT这个地址,我讲的是spring2.5.5版本的

我试了是可以的。

ApplicationContext application = (ApplicationContext)req.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");

这样我取得了我想要的ApplicationContext

我不知你初始化Spring是用的哪个,如果用org.springframework.web.servlet.DispatcherServlet进行初始化,在DispatcherServlet extends FrameworkServlet
FrameworkServlet.initWebApplicationContext()方法中有
getServletContext().setAttribute(attrName, wac);

debug时发现attrName="org.springframework.web.servlet.FrameworkServlet.CONTEXT.dis" 不知道你是不是说的这种情况。
2 楼 zywang 2010-09-20  
你找找用Struts集成Spring的时候wac被保存到什么地方去的吧,貌似不是org.springframework.web.context.WebApplicationContext.ROOT这个地址,我讲的是spring2.5.5版本的
1 楼 dxm1986 2010-09-19  
我晕,某些标红的地方,又变成<SPAN style="COLOR: #ff0000">****</SPAN>了,javaeye的编辑器有问题呀。

相关推荐

    Spring获取ApplicationContext对象工具类的实现方法

    但有时候,特别是在多模块项目或者非Web应用中,我们需要一种更加灵活的方式来获取ApplicationContext。 一种常见的做法是实现一个工具类,通过静态方法封装ApplicationContext的获取逻辑。下面是一个简单的示例: ...

    Spring中ApplicationContext加载机制

    在 Web 应用程序中,ApplicationContext 的加载机制是非常重要的, Spring 提供了多种方式来加载 ApplicationContext。 首先,Spring 提供了两种选择来加载 ApplicationContext:ContextLoaderListener 和 ...

    获取spring容器的方法

    本文将深入探讨几种常见的获取Spring容器的方法,包括使用`ApplicationContext`、通过`ServletContext`、利用`ApplicationObjectSupport`、`WebApplicationObjectSupport`以及实现`ApplicationContextAware`接口等。...

    线程中获取spring 注解bean

    当需要在线程中获取Spring注解的bean时,有几种常见的方法: 1. **ThreadLocal**:Spring提供了一种名为`ThreadLocalTargetSource`的特殊`TargetSource`实现,可以将bean实例绑定到当前线程。这样,每个线程都有其...

    Spring + struts 整合的三种主要方式

    在Java Web开发领域,Spring框架和Struts框架都是非常重要的技术。Spring框架以其强大的依赖注入(DI)和面向切面编程(AOP)功能,为Java应用提供了轻量级的解决方案。而Struts框架则是一个基于MVC架构模式的Web...

    Spring 和 struts 整合的三种方式

    以下将详细阐述Spring与Struts整合的三种方式: 1. **使用Spring的ActionSupport** 这种方式是通过让Struts的Action类继承Spring的`ActionSupport`类,使Action类能够访问Spring的ApplicationContext。首先,在`...

    Java中Spring获取bean方法小结

    在Java开发中,Spring框架是不可或缺的一部分,它提供了一个强大的依赖注入(DI)和面向切面编程(AOP)的容器。Spring的核心在于其BeanFactory和ApplicationContext,它们使得对象的管理和装配变得简单。这里我们将...

    在Servlet直接获取Spring框架中的Bean.docx

    在Java Web开发中,Spring框架提供了强大的依赖注入和管理组件的能力。当我们在Servlet环境中工作时,有时需要在Servlet中直接访问由Spring管理的Bean,以便利用Spring提供的服务和功能。以下是如何在Servlet中直接...

    Spring如何获取Bean

    这种方式通常用于 Web 应用程序中,因为它可以从 ServletContext 中获取 ApplicationContext。 例如,我们可以在 web.xml 文件中定义一个 listener,如下所示: ```xml &lt;listener-class&gt;org.springframework.web...

    Java获取Bean的几种方式.pdf

    Spring提供了`ContextLoader`和`WebApplicationContextUtils`等工具类,可以从当前线程或ServletContext中获取ApplicationContext。 ```java // 在非Web应用中 ApplicationContext ac = ContextLoader....

    SpringMVC+Spring+Mybatis集成开发环境

    在IT行业中,SpringMVC、Spring和Mybatis是三大核心框架,它们的集成使用是Java Web开发中的常见实践。这个集成开发环境旨在提供一个高效、灵活的开发平台,以实现业务逻辑与数据访问的分离,提高代码的可维护性和可...

    几种spring获取bean的方法.txt

    此外,在实际开发中还可能遇到其他获取Bean的方式,比如使用`ApplicationContext`的子类如`ClassPathXmlApplicationContext`或`FileSystemXmlApplicationContext`等。选择哪种方式取决于具体的应用场景和个人喜好。...

    在Eclipse 中创建Spring的 Web应用.doc

    在Eclipse中创建一个基于Spring的Web应用涉及多个步骤,主要涵盖了Spring框架的Web模块、ApplicationContext的使用以及在Web容器中的配置。以下是详细的过程和相关知识点: 1. **Spring Web模块**: Spring框架...

    Spring通过ApplicationContext主动获取bean的方法讲解

    这个问题在实际开发中非常常见,特别是在异步线程或某些特殊情况下无法使用AutoWired和Component注解时,就需要使用ApplicationContext来获取bean。 首先,我们需要了解什么是ApplicationContext。...

    spring 配合 webserver 开发实例

    在开发Web应用时,Spring框架和Web服务器的配合使用是至关重要的。本实例将深入探讨如何利用Spring框架与Web服务器(如...通过这个实例,你可以掌握Spring与Web服务器协作开发的完整流程,进一步提升你的Web开发技能。

    三种整合 Struts 应用程序与 Spring 的方式

    Struts 与 Spring 的整合是Java Web开发中常见的需求,因为这两个框架分别在MVC模式和依赖注入(DI)及面向切面编程(AOP)方面提供了强大的功能。本文主要介绍了三种整合Struts应用程序与Spring的方法。 首先,Spring...

    spring+ibatis+web

    在IT行业中,Spring、iBATIS和Struts1是经典的Java Web开发框架,它们的集成应用为开发者提供了灵活且强大的后端服务构建能力。本文将深入探讨这些技术的结合使用,以及它们如何协同工作来创建高效的应用程序。 ...

    spring开发相关jar包(json,springweb,springmvc,jdbc等)

    在Spring框架的开发中,涉及了多个...以上就是标题和描述中提到的关键知识点,它们构成了Spring开发的基础,并且在实际的Java Web项目中扮演着重要角色。了解和掌握这些概念,对于成为一名熟练的Spring开发者至关重要。

    Mybatis与Spring整合创建Web项目

    总结,Mybatis与Spring的整合创建Web项目,是现代Java Web开发中的常见实践,它能够提高开发效率,降低维护成本。理解并熟练掌握这种整合方式,对于提升开发者在企业级应用开发中的技能至关重要。

Global site tag (gtag.js) - Google Analytics