spring中spring的容器是什么指的是什么

Spring之容器和配置初识
通过前两篇文章的学习,对spring有了初步的认识,并且应该认识到,spring的核心在于控制反转IOC和依赖注入DI
spring是怎么达到这个目标呢?
我们都已经知道理利用spring框架,依赖的注入由spring容器来进行,那么当然需要一些配置信息来告诉spring怎么注入。这就是spring元数据的配置(即bean的配置)。
综上,spring通过容器和元数据的配置来实现基本的功能。
通过本文达到,两个目标:
1.初步的认识spring容器。
2.初步认识spring元数据的配置
ApplicationContext
接口 org.springframework.context.ApplicationContext 代表了Spring IoC容器,它负责实例化、配置、组装beans. Spring通过读取元数据的配置进行以上的操作,元数据的配置有多种形式,包括xml、注解和JSR标准。
且Spring 提供了几种ApplicationContext的实现,如ClassPathXmlApplicationContext、FileSystemXmlApplicationContext,顾名思义,它们读取基于xml的元数据配置。
下面通过一个简单的例子说明spring容器的简单用法和spring XMl元数据配置。
这个例子很简单,就是获取中的用户,然后打印出来。整个程序分为三各层次,模拟dao、service和客户端,客户端调用service,service调用dao。Service对dao的依赖由spring容器来管理。代码结构如下图:
代码由客户端调用开始,一点点深入底层,其中的注释详细的说明了相关的要点。
首先是User类:
public class User {
* @param id
* @param name
public User(int id, String name) {
this.name =
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
客户端由main函数调用模拟,代码如下:
package com.
import org.springframework.context.ApplicationC
import org.springframework.context.support.ClassPathXmlApplicationC
import com.test.service.UserS
* @Description: 客户端首先初始化spring容器,然后从容器中获取benn调用其相应方法。和传统不一样的地方在于,
* 业务对象UserService 的实例化不是由客户端通过new 来产生,而是直接从spring容器中获取。
* 本示例例环境为eclipse
public class TestMain {
public static void main(String[] args) {
* ApplicationContext代表spring容器,而ClassPathXmlApplicationContext是它的一个实现,它从类路径下读取相应的
xml 元数据配置,并初始化容器。其中allbean.xml是相应的元数据配置
ApplicationContext context = new ClassPathXmlApplicationContext("allbean.xml");
//从容器中获取名称为 user 的 userService 对象,这个名称在配置文件之后配置。
UserService userService = context.getBean("user", UserService.class);
System.out.println(userService.getUser());
//可以和传统方式相比较:
UserService user = new UserServiceIml();
UserDao dao = new UserDaoImp();
((UserServiceIml)user).setUserDao(dao);
System.out.println(user.getUser());
allbean.xml内容如下:
Service层包含一个接口,一个实现类,一个Spring的xml元数据配置文件:
public interface UserService {
public List getUser();
*实现类,有个字段引用了UserDao接口,其具体的业务逻辑调用
{@link UserDao#getUser()}实现
*且有一个set方法,此set方法由spring 容器注入使用,如果没有回报错,
*这是spring容器依赖注入的一种方法--setter注入
public class UserServiceIml implements UserService{
private UserDao userD
public List getUser() {
return userDao.getUser();
public void setUserDao(UserDao userDao) {
this.userDao = userD
Xml元数据配置如下,它定义了userServicebean,且定义了它的依赖:
Dao层定义了相应的 接口,实现类和 xml元数据配置,首先是接口和实现类:
public interface UserDao {
public List getUser();
public class UserDaoImp implements UserDao{
public List getUser() {
List res = new ArrayList();
User a = new User(1, "aa");
User b = new User(2, "bb");
res.add(a);
res.add(b);
然后是xml配置文件,定义了一个名称为userDao,实现类为com.test.dao.UserDaoImp 的bean:
运行客户端程序,输入如下,和预期一样:
此文章简单的说明了Spring容器的用法和相关bean的配置。从一个极简单例子入手,自顶向下的进行剖析,并简单的分析了Spring的优点。当然本人目前水平有限,不当之处,欢迎指正。
另外,关于Spring bean的配置还有很多地方需要深入理解,不仅仅是Xml,还有注解、JSR以及他们的组合。bean的配置也包含其他方面,如基本数据类型、集合类型、生命周期、范围、容器扩展点等,而这些都属于spring的核心功能,需要逐步理解掌握,期待大家共同进步。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'在web器皿中获取spring容器中的bean对象 - Web前端当前位置:& &&&在web器皿中获取spring容器中的bean对象在web器皿中获取spring容器中的bean对象&&网友分享于:&&浏览:0次在web容器中获取spring容器中的bean对象
最近在做一个插件开发,即动态的上传插件之后,插件能够解决我们的需求,但是具体的处理方法处理的过程中需要对数据库进行操作,由于使用的是springMVC,在service层中配置了相关的dao层,因此只需要能够获取service层对象即可,但是这个对象必须由spring来提供,否则service对象里面的属性需要逐一实例化。
首先,我们需要了解ContextLoaderListener与DispatcherServlet所加载的applicationContext的区别?
参考:/sir_876/blog/static//
spring通过在web.xml 中配置ContextLoaderListener 来加载context配置文件,在DispatcherServlet中也可以来加载spring context配置文件,那么这两个有什么区别呢?
ContextLoaderListener中加载的context成功后,spring 将 applicationContext存放在ServletContext中key值为"org.springframework.web.context.WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE"的attribute 中。
下面是我看ContextLoader类的源代码的解析:
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
//在系统加载的时候servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)的值为null
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!");
Log logger = LogFactory.getLog(org / springframework / web / context / ContextLoader);
servletContext.log("Initializing Spring root WebApplicationContext");
if (logger.isInfoEnabled())
<("Root WebApplicationContext: initialization started");
long startTime = System.currentTimeMillis();
//private WebApplicationC
//public interface WebApplicationContext extends ApplicationContext
//WebApplicationContext是ApplicationContext的子类
if (context == null)
//servletContext这个是web.xml配置文件中的信息,其中就包含是否配置了contextConfigLocation参数
//如果有则读取指定位置的配置文件,如果没有则从默认的位置找配置文件,如果没有则会报错
&context-param&
&param-name&contextConfigLocation&/param-name&
&param-value&
/WEB-INF/config/spring/spring_application_*.xml,
/WEB-INF/myspring-servlet.xml
&/param-value&
&/context-param&
//现在的context对象已经有了ApplicationContext对象的功能,即可以生成spring容器中定义的bean对象
context = createWebApplicationContext(servletContext);
if (context instanceof ConfigurableWebApplicationContext)
configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext) context, servletContext);
//将已经有了ApplicationContext功能的对象存放在servletContext对象中,key的值就是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
//这个对象在整个应用系统的任何时刻任何地方都可以访问,相当于一个共享的资源池
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == org / springframework / web / context / ContextLoader.getClassLoader())
currentContext =
else if (ccl != null)
currentContextPerThread.put(ccl, context);
if (logger.isDebugEnabled())
logger.debug((new StringBuilder("Published root WebApplicationContext as ServletContext attribute with name [")).append(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)
.append("]").toString());
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startT
<((new StringBuilder("Root WebApplicationContext: initialization completed in ")).append(elapsedTime).append(" ms").toString());
} catch (RuntimeException ex) {
logger.error("Context initialization failed", ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
} catch (Error err) {
logger.error("Context initialization failed", err);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
因此有如下三种方法来获取ApplicationContext对象
1、servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
2、WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)
3、WebApplicationContextUtils.getWebApplicationContext(servletContext)
HttpServlet --& HttpServletBean --& FrameworkServlet --& DispatcherServlet
在web.xml文件中配置了如下代码:
&!-- 使用spring 的MVC来管理 --&
&servlet-name&myspring&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&load-on-startup&1&/load-on-startup&
&/servlet&
&servlet-mapping&
&servlet-name&myspring&/servlet-name&
&url-pattern&*.do&/url-pattern&
&/servlet-mapping&
也就是说会执行servlet的init()方法,而该方法在HttpServletBean类中,在init()该方法中有一个initServletBean()方法,这个initServletBean()方法被FrameworkServlet类重写,在initServletBean()中会调用initWebApplicationContext()方法,下面看看initWebApplicationContext()里面的详细内容:
protected WebApplicationContext initWebApplicationContext() {
//得到web.xml中的上下文
//这里是为了兼容ContextLoaderListener类已经获取到spring的applicationContext了,也就没有必要再重新加载一次spring的配置文件了。
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac =
if (webApplicationContext != null) {
wac = webApplicationC
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)
if (!cwac.isActive()) {
if (cwac.getParent() == null)
cwac.setParent(rootContext);
configureAndRefreshWebApplicationContext(cwac);
//如果没有配置ContextLoaderListener类,则需要自己加载spring的配置文件了
if (wac == null)
//查看能否找到applicationContext对象
wac = findWebApplicationContext();
if (wac == null)
//找不到ApplicationContext对象就自己创建一个ApplicationContext对象
wac = createWebApplicationContext(rootContext);
if (!refreshEventReceived)
onRefresh(wac);
if (publishContext) {
//这里得到的值是org.springframework.web.servlet.FrameworkServlet.CONTEXT.{web.xml配置文件中DispatcherServlet类servlet的名字}
//因此,在我的实例中的名字是org.springframework.web.servlet.FrameworkServlet.CONTEXT.myspring
String attrName = getServletContextAttributeName();
//将ApplicationContext对象存储在ServletContext上下文中,key的值为attrName
getServletContext().setAttribute(attrName, wac);
if (logger.isDebugEnabled())
logger.debug((new StringBuilder("Published WebApplicationContext of servlet '")).append(getServletName()).append("' as ServletContext attribute with name [").append(attrName)
.append("]").toString());
在每次request请求时,DispatcherServlet会将此applicationContext存放在request中attribute 值为 org.springframework.web.servlet.DispatcherServlet.CONTEXT中 (request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());)。
可以通过如下两种方式来获取ApplicationContext对象
1、 RequestContextUtils.getWebApplicationContext(ServletRequest request)
2、 WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)
备注:attrname实际上就是org.springframework.web.servlet.FrameworkServlet.CONTEXT.{web.xml配置文件中DispatcherServlet类servlet的名字}
从上面的分析可以看出,DispatcherServlet所加载的applicationContext可以认为是mvc私有的context,由于保存在servletContext中的key值与通过ContextLoaderListener加载进来的applicationContext使用的 key值不相同,因此如果只使用DispatcherServlet加载context的话,如果程序中有地方使用 WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 来试图获取applicationContext时,就会抛出"No WebApplicationContext found: no ContextLoaderListener registered?"的exception。
上面提到了很多ServletContext类,那么下面就解释一下他的功能:
ServletContext : 每一个web应用都有一个 ServletContext与之相关联。 ServletContext对象在应用启动的被创建,在应用关闭的时候被销毁。 ServletContext在全局范围内有效,类似于应用中的一个全局变量。
ServletContextListener: 使用listener接口,开发者能够在为客户端请求提供服务之前向ServletContext中添加任意的对象。这个对象在ServletContext启动的时候被初始化,然后在ServletContext整个运行期间都是可见的。
在 Servlet API 中有一个 ServletContextListener 接口,它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期。
当Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent 事件,该事件由ServletContextListener 来处理。在 ServletContextListener 接口中定义了处理ServletContextEvent 事件的两个方法。
解决办法:
在web容器中添加一个继承ServletContextListener接口的对象,然后给这个类添加一个ServletContext属性,在系统启动的时候就赋值给它。
import javax.servlet.ServletContextE
import javax.servlet.ServletContextL
import org.springframework.context.ApplicationC
import org.springframework.web.context.WebApplicationC
import org.springframework.web.context.support.WebApplicationContextU
public class SpringInit implements ServletContextListener {
private static WebApplicationContext springC
public SpringInit() {
public void contextInitialized(ServletContextEvent event) {
springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
public void contextDestroyed(ServletContextEvent event) {
public static ApplicationContext getApplicationContext() {
return springC
备注:之所以将 ServletContext 属性设置为 static 是因为在不同的 servlet 对象中获取 MessageInteceptorFilter 对象的属性是获取不到的,因此将其设置为类的属性,如果MessageInteceptorFilter类存在就能够找到这个属性的具体值。
下面这段代码是在网上找的
import javax.servlet.ServletContextE
import javax.servlet.ServletContextL
import org.springframework.context.ApplicationC
import org.springframework.web.context.WebApplicationC
import org.springframework.web.context.support.WebApplicationContextU
public class SpringInit implements ServletContextListener {
public SpringInit() {
//获取spring的applicationContext
public void contextInitialized(ServletContextEvent event) {
springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
//ServletContext对象在应用启动的被创建,在应用关闭的时候被销毁。 ServletContext在全局范围内有效,类似于应用中的一个全局变量。
event.getServletContext().setAttribute("springContext",springContext);
public void contextDestroyed(ServletContextEvent event) {
获取spring容器中的对象
@RequestMapping(value = "/sendMessageFromToCont")
public String sendMessageFromToCont(HttpServletRequest request, HttpServletResponse response) {
request.getSession().getServletContext().getAttribute("springContext");
return "adtec_message/imjwchat-testim";
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有> Spring跟Web容器整合的内部实现
Spring跟Web容器整合的内部实现
sec100 & &
发布时间: & &
浏览:1 & &
回复:0 & &
悬赏:0.0希赛币
Spring和Web容器整合的内部实现
  Spring和Web应用的整合配置如下
  &context-param&
  &param-name&contextConfigLocation&/param-name&
  &param-value&classpath:applicationContext.xml&/param-value&
  &/context-param&
  &listener&
  &listener-class&
  org.springframeworntext.ContextLoaderListener
  &/listener-class&
  &/listener&
  通过上面的配置Spring就和Web应用整合了,之前我一直不明白,它内部的整合方式是怎样的,在整合后Spring和Web应用上下文的关系是怎样的,所以最近深入了源代码去看看内部的机制,首先当让是从ContextLoaderListener这个类入手了,这是一个ServletContextListener监听器类的实现类,在Web应用启动的时候会去加载这个类,调用相关的方法,代码如下:
  public class ContextLoaderListener
extends ContextLoader implements ServletContextListener {
private ContextLoader contextL
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader =
this.contextLoader.initWebApplicationContext(event.getServletContext());
protected ContextLoader createContextLoader() {
public ContextLoader getContextLoader() {
return this.contextL
public void contextDestroyed(ServletContextEvent event) {
if (this.contextLoader != null) {
this.contextLoader.closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
  上面红色标注的是关键代码,它调用了父类ContextLoader的initWebApplicationContext()方法,接下来就去看看在那个方法里面做了些什么,先看ContextLoader这个类,这个类内容比较多,下面只列出一些关键代码:
  public class ContextLoader {
public static final String CONTEXT_CLASS_PARAM = "contextClass";
public static final String CONTEXT_ID_PARAM = "contextId";
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector";
public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey";
private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
private static final Properties defaultS
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
catch (IOException ex) {
throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
//指定了一个类加载器只能实例化一个Spring容器
private static final Map&ClassLoader, WebApplicationContext& currentContextPerThread =
new ConcurrentHashMap&ClassLoader, WebApplicationContext&(1);
private static volatile WebApplicationContext currentC
private WebApplicationC
//ContextLoaderListener类中就是调用了这个方法
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
ApplicationContext parent = loadParentContext(servletContext);
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdowntext = createWebApplicationContext(servletContext, parent);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
return this.
protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {
Class& & contextClass = determineContextClass(sc);
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setParent(parent);
wac.setServletContext(sc);
wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));
customizeContext(sc, wac);
wac.refresh();
protected Class& & determineContextClass(ServletContext servletContext) {
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
if (contextClassName != null) {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load custom context class [" + contextClassName + "]", ex);
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load default context class [" + contextClassName + "]", ex);
  在这个类的静态代码块里面加载了同路径下的ContextLoader.properties这个属性文件,代开它,里面只有一条
  org.springframeworntext.WebApplicationContext=org.springframeworntext.support.XmlWebApplicationContex
  t,这个是指定了Spring容器的具体实现类,要整合Web,自然是要XmlWebApplicationContext了。
  看initWebApplicationContext方法,接着调用createWebApplicationContext(servletContext, parent)方法中,创建出WebApplicationContext,在这个方法里面,determineContext——确定Spring容器的具体实现类,然后使用BeanUtils.instantiateClass()来初始化XmlWebApplicationContext类,注意,这里只是初始化这个类,并没有启动Spring容器,要启动容器,还需要一个非常关键的东西,那就是配置文件。在createWebApplicationContext的最后又几条红色加深的代码,非常关键,
  wac.setServletContext(sc);//将当前的ServletContext传给即将启动的Spring容器
  wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));//设置容器启动时加载的
spring配置文件,在这里就是要使用web.xml中配置的contextConfigLocation参数所指定的配
置文件位置了
  customizeContext(sc, wac);
  wac.refresh();//在这里启动Spring容器,这里其实是调用父类AbstractApplicationContext的refresh()方法
  综上所述,Spring和Web应用的整合这是在web应用启动的时候通过一个监听器去启动了XmlWebApplicationContext Spring容器,并将这个容器实例放入到ServletContext的Map里,Map里以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,对于的字符串也就是WebApplicationContext.class.getName() + ".ROOT";也就是"org.springframeworntext.WebApplicationContext.ROOT",在Servlet环境下可以通过这个来访问Spring容器,同样Spring中当然也可以访问ServletContext。
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&

我要回帖

更多关于 spring容器启动过程 的文章

 

随机推荐