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

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
分享到:
评论

相关推荐

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    12.6 整合Struts、Spring和Hibernate实现用户管理 12.6.1 Struts、Spring和Hibernate的整合方式 12.6.2 编写用户注册画面regedit.jsp 12.6.3 编写用户登录画面login.jsp 12.6.4 编写注册控制器RegeditAction.java ...

    struts2+spring+hibernate整合示例

    web容器中(web.xml)中添加struts2 filter以及spring 监听器。 b 在struts.xml中添加action,使用通配符的方式 , 注意这里和单独struts2不同的地方: class属性指向的是bean 的 id ,这里我们配置bean采用spring ...

    Spring攻略PDF版

     第11章 整合Spring与其他Web框架   第12章 Spring对测试的支持  第三部分 高级主题  第13章 Spring Security框架   第14章 Spring Portlet MVC框架   第15章 Spring Web Flow   第16章 ...

    Spring攻略中文版PDF

     第11章 整合Spring与其他Web框架   第12章 Spring对测试的支持  第三部分 高级主题  第13章 Spring Security框架   第14章 Spring Portlet MVC框架   第15章 Spring Web Flow   第16章 ...

    Spring攻略英文版(附带源码)

     第11章 整合Spring与其他Web框架   第12章 Spring对测试的支持  第三部分 高级主题  第13章 Spring Security框架   第14章 Spring Portlet MVC框架   第15章 Spring Web Flow   第16章 Spring...

    Spring、SpringMVC和Mybatis框架整合包

    手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis 博客地址:http://blog.csdn.net/qq598535550/article/details/51703190 我们看招聘信息的时候,经常会看到这一点,需要具备SSH框架的技能;而且在大...

    Spring Framework 5 中文文档

    1. 入门指南 2. 介绍Spring框架 3. IoC容器 4. 资源 5. 验证、数据绑定和类型转换 6. Spring表达式语言 ...24. 使用Spring提供远程和WEB服务 25. 整合EJB 26. JMS 28. 使用Spring提供远程和WEB服务 32. 缓存

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    12.6 整合Struts、Spring和Hibernate实现用户管理 12.6.1 Struts、Spring和Hibernate的整合方式 12.6.2 编写用户注册画面regedit.jsp 12.6.3 编写用户登录画面login.jsp 12.6.4 编写注册控制器RegeditAction.java ...

    Spring+3.x企业应用开发实战光盘源码(全)

     第5章:对Spring容器进行解构,从内部探究Spring容器的体系结构和运行流程。此外,我们还将对Spring容器一些高级主题进行深入的阐述。  第6章:我们从Spring AOP的底层实现技术入手,一步步深入到Spring AOP的...

    手动整合Struts1.3 +hibernate3.2+Spring2.5 .txt

    手动整合Struts1.3 +hibernate3.2+Spring2.5 ,在web容器中实例化spring容器, 在web容器中配置struts 在web容器中配置hibernate

    第17讲 Spring、hibernate和Struts2的整合

    ①在web.xml中配置ApplicationContext.xml,并使用ContextLoader监听器实例化spring容器 ②把action交给spring管理,即在spring配置文件中定义action Bean并使用依赖注入功能在action中注入业务Bean,同时修改作用域...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (2)

    12.6 整合Struts、Spring和Hibernate实现用户管理 12.6.1 Struts、Spring和Hibernate的整合方式 12.6.2 编写用户注册画面regedit.jsp 12.6.3 编写用户登录画面login.jsp 12.6.4 编写注册控制器RegeditAction.java ...

    SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis两个开源框架整合而成(Spring

    Spring框架主要由七部分组成,分别是Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。它解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、...

    springMVC+Spring+Mybatis+Maven整合代码案例

    4、搭建spring和mybatis的配置:spring-mybatis.xm(扫描dao)) 5、测试Spring+mybatis的框架搭建,写单元测试JUnit,测试事务配置等:model--&gt;dao(mapper)--&gt;service--&gt;test 6、映入SpringMVC:配置...

    spring-boot-starter-netty:一个基于Netty实现的Spring Boot内置Servlet容器。a Spring Boot embedded servlet container project base on netty API (4.1.12.Final)

    这是一个基于netty API(4.1.12.Final)的Spring Boot嵌入式servlet容器项目。 该项目已发布到Maven中心存储库中,请参阅 。 Maven依赖 将以下依赖项添加到您的Maven项目中: &lt;!-- exludes embedded Tomcat --...

    Maven整合ssm框架.zip

    ssm整合步骤: 第一步:mybatis单独测试 1.引入mybatis,mysql依赖 2.创建实体和dao层。... 整合的要点:就是让springmvc从servletContext中获取spring容器即可 1.在web.xml中配置spring的监听器即可。

    Spring.html

    Spring整合web 1.导入依赖spring-web 2.配置ContextLoadListener 3.配置 &lt;!--全局初始化参数--&gt; &lt;context-param&gt; &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt; &lt;param-value&gt;classpath:...

    整合Mybatis和Spring框架进行注解开发SSM框架的学习与应用-Java EE企业级应用开发学习记录(第十天)

    本资源记录了在Java EE企业级应用开发学习过程中的第十天内容,重点关注了整合Spring、Spring MVC和MyBatis(SSM框架)进行注解开发的学习和应用。通过这一天的学习,您将掌握如何构建强大的Web应用程序,同时提供了...

    Struts+Spring+Hibernate 整合教程.pdf

    用java 来建立一个很有价值的web 应用不是一个简单的任务。在架构这个应用时要考虑很多的因素 和问题。从更高的层次来看,开发人员面临着关于如何构建用户接口,何处驻留业务逻辑,以及如何 实现数据持久性这些问题...

Global site tag (gtag.js) - Google Analytics