`
shiyiyue513
  • 浏览: 1746 次
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

Spring和Web容器整合的内部实现

 
阅读更多

Spring和Web应用的整合配置如下

 

<context-param>

       <param-name>contextConfigLocation</param-name>

       <param-value>classpath:applicationContext.xml</param-value>

</context-param>

 

<listener>

    <listener-class>

      org.springframework.web.context.ContextLoaderListener

   </listener-class>

</listener>

通过上面的配置Spring就和Web应用整合了,之前我一直不明白,它内部的整合方式是怎样的,在整合后Spring和Web应用上下文的关系是怎样的,所以最近深入了源代码去看看内部的机制,首先当让是从ContextLoaderListener这个类入手了,这是一个ServletContextListener监听器类的实现类,在Web应用启动的时候会去加载这个类,调用相关的方法,代码如下:

 

 

public class ContextLoaderListener  extends ContextLoader implements ServletContextListener {

	private ContextLoader contextLoader;


	public void contextInitialized(ServletContextEvent event) {
		this.contextLoader = createContextLoader();
		if (this.contextLoader == null) {
			this.contextLoader = this;
		}
		this.contextLoader.initWebApplicationContext(event.getServletContext());
	}

	
	protected ContextLoader createContextLoader() {
		return null;
	}

	
	public ContextLoader getContextLoader() {
		return this.contextLoader;
	}


	
	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 defaultStrategies;

	static {
		
		try {
			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 currentContext;

	
	private WebApplicationContext context;

	

       //ContextLoaderListener类中就是调用了这个方法
	public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		
		try {
			
			ApplicationContext parent = loadParentContext(servletContext);

			// Store context in local instance variable, to guarantee that
			// it is available on ServletContext shutdown.
			this.context = createWebApplicationContext(servletContext, parent);
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

			ClassLoader ccl = Thread.currentThread().getContextClassLoader();
			
			return this.context;
		
	}

	
	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();
		return wac;
	}

	
	protected Class<?> determineContextClass(ServletContext servletContext) {
		String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
		if (contextClassName != null) {
			try {
				return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load custom context class [" + contextClassName + "]", ex);
			}
		}
		else {
			contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
			try {
				return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
			}
			catch (ClassNotFoundException ex) {
				throw new ApplicationContextException(
						"Failed to load default context class [" + contextClassName + "]", ex);
			}
		}
	}

}
 

 

      在这个类的静态代码块里面加载了同路径下的ContextLoader.properties这个属性文件,代开它,里面只有一条

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.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.springframework.web.context.WebApplicationContext.ROOT",在Servlet环境下可以通过这个来访问Spring容器,同样Spring中当然也可以访问ServletContext。

 

 

 

 

0
0
分享到:
评论

相关推荐

    Spring的web整合包

    此外,还包括了Model、View和Controller的接口和实现,如Controller接口、SimpleFormController、CommandController等,以及ModelAndView对象,用于在控制器和视图之间传递数据。 接下来,Spring Web模块提供了对...

    web项目整合spring

    "web项目整合spring"这个主题,意味着我们要探讨如何将Spring框架与Web项目结合,以便实现更高效、模块化的开发流程。在这个过程中,`applicationContext.xml`文件扮演着至关重要的角色,它是Spring应用上下文的配置...

    spring springmvc mybatis框架整合需要的jar包

    在Java Web开发中,Spring、SpringMVC和MyBatis是三个非常重要的开源框架,它们分别负责不同的职责:Spring作为核心容器管理应用组件,SpringMVC处理Web请求,而MyBatis则专注于数据库操作。将这三个框架整合在一起...

    spring2与quartz在Web整合

    通过理解和掌握这些知识点,开发者能够有效地在 Spring 2 和 Quartz 之间建立桥梁,实现 Web 应用中的复杂任务调度功能。对于出现问题的整合,开发者可以通过分析源码、查看日志和调试来定位和解决问题,进一步提升...

    spring与hibernate的整合

    下面我们将深入探讨如何整合这两个框架,并展示如何在 Spring 容器中配置 SessionFactory 以及基于 Hibernate 原生 API 实现 DAO。 1. Spring 中配置 SessionFactory 在 Spring 容器中创建 SessionFactory 是整合...

    在Web项目中集成Spring

    在现代Web开发中,Spring Boot简化了Spring的集成过程,通过自动配置和起步依赖,使得开发者可以更快地搭建和运行Spring应用。但不论使用哪种方式,理解Spring在Web项目中的集成原理和组件工作方式都是非常重要的。 ...

    spring和axis 整合

    在IT行业中,Spring框架和Apache Axis2是两个重要的技术组件,它们分别用于处理Java应用程序的依赖管理和Web服务的实现与部署。Spring是一个全面的后端开发框架,它提供了丰富的功能,如依赖注入、面向切面编程(AOP...

    ZK+spring+hibernate的整合

    通过上述步骤,我们就能实现ZK、Spring和Hibernate的深度整合,构建出一个强大的Java Web应用。对于初学者来说,理解并掌握这个整合过程,不仅能提升技术水平,也能为后续的项目开发打下坚实基础。在实践中,不断...

    Spring整合Jetty开发web应用的例程

    在Java Web开发中,Spring框架和Jetty服务器的整合提供了轻量级且高效的应用部署解决方案。这个例程展示了如何利用Spring来启动和管理Jetty服务器,以构建和运行Web应用程序。下面将详细介绍这一过程中的关键知识点...

    struts2 + spring 3 + hibernate3.3整合实现图书馆管理管理

    Struts2、Spring和Hibernate是Java Web开发中的三大框架,它们的整合应用广泛用于构建复杂的Web应用程序,如本例中的图书馆管理系统。这个系统实现了用户登录和注册功能,并且提供了对书籍表的操作,包括增、删、改...

    struts2整合spring实现拦截器

    Struts2 和 Spring 的整合是Java Web开发中的常见实践,这两种框架的结合可以极大地提高应用的可维护性和灵活性。在本文中,我们将深入探讨如何实现Struts2与Spring的集成,以及利用拦截器来增强应用的功能。 首先...

    OSGI整合Spring、Mybatis、Spring MVC实现一个登录应用案例

    在这个案例中,我们将探讨如何整合OSGI、Spring、Mybatis以及Spring MVC来实现一个登录应用。这个教程旨在帮助开发者理解如何在OSGI环境中集成这些流行的Java技术,以构建灵活且可扩展的应用程序。 首先,我们需要...

    OSGi与Web容器的整合

    将OSGi与Web容器整合,可以实现更加灵活和模块化的Web应用开发和部署。 **1. OSGi Bundle放入Web容器中运行** 这是通过像Equinox的Servlet Bridge这样的技术实现的,它充当了一个桥梁,让OSGi Bundle可以在传统的...

    SpringMybatisSpringMvc整合包

    这个整合包中的jar包包括了Spring框架的core、context、aop、beans、web等模块,Mybatis的核心库和Spring Mybatis的整合模块,以及Spring MVC的相关组件。这些jar包涵盖了运行Spring、Mybatis和Spring MVC应用所需的...

    Spring-Mybatis整合

    - **Service 层**:创建 Service 层接口和实现类,通过 Spring 注解或 XML 配置方式注入对应的 Mapper。 - **Controller 层**:创建 Controller 类,注入 Service 实例,处理HTTP请求并调用 Service 方法。 4. **...

    Java EE互联网轻量级框架整合开发 SSM框架(Spring MVC+Spring+MyBatis)和Redis实现.rar

    Java EE互联网轻量级框架整合开发,主要集中在SSM框架的使用上,即Spring MVC、Spring和MyBatis的集成,以及Redis缓存技术的引入。这个主题旨在提高Web应用的开发效率,优化性能,同时降低项目的复杂度。 首先,...

    spring和mybatis整合小案例

    这个"spring和mybatis整合小案例"项目,展示了如何将两者结合,构建一个可运行的Java Web应用。通过这个案例,开发者可以更好地理解和掌握Spring与MyBatis的整合技巧,提高开发效率,减少出错的可能性。

    Spring与Struts 2整合.zip

    整合Spring和Struts 2可以使开发更加便捷,因为Spring的IoC容器可以帮助管理对象的生命周期,而Struts 2则专注于处理请求和展现逻辑。这种整合方式在大型项目中非常常见,有助于提升代码质量和团队协作效率。 在...

    spring ioc容器部署实现

    ### Spring IoC容器部署实现详解 #### 一、Spring IoC容器概述 Spring框架的核心特性之一就是Inversion of Control(IoC),也被称为Dependency Injection(DI)。IoC容器是Spring框架的重要组成部分,它负责管理...

Global site tag (gtag.js) - Google Analytics