自我分析-Spring IOC在Web应用的启动和销毁

Spring IOC容器通过ServletContextListener对servlet容器的生命周期监听,从而实现了IOC的启动和销毁。

注意:

1.分析框架代码时,要常使用类继承、调用关系等快捷键,可以更高效的学习,快捷键可以设置成你习惯的按键;

2.本文重在怎么自我分析框架代码,所以对其中解析需自己实际跟踪代码实践方可;

3.spring源代码版本 spring-framework-3.2.1.RELEASE。

预览

javax.servlet.ServletContext,Servlet容器接口。

javax.servlet.ServletContextListener,Servlet容器生命周期监听接口。

org.springframework.web.context.ContextLoaderListener,Spring IOC容器生命周期监听类。

org.springframework.web.context.ContextLoader,Spring
IOC容器启动和销毁。

配置-监听ServletContext生命周期

在web.xml中spring配置了对ServletContext生命周期的监听,当Web容器启动和销毁时,触发Spring定义的IOC容器的启动和销毁,具体配置如下:

<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>

入口-ContextLoaderListener对Spring IOC初始化和销毁

当web容器启动时会触发contextInitialized方法对spring ioc容器进行初始化,销毁时会触发contextDestroyed方法对spring ioc容器进行销毁,ServletContextListener接口如下:

    public void contextInitialized ( ServletContextEvent sce );  // ServletContext启动时触发

    public void contextDestroyed ( ServletContextEvent sce );    // ServletContext销毁时触发

Spring IOC启动

spring ioc容器初始化具体代码如下:

org.springframework.web.context.ContextLoaderListener

	public void contextInitialized(ServletContextEvent event) {
		this.contextLoader = createContextLoader();
		if (this.contextLoader == null) {
			this.contextLoader = this;
		}
		// 对spring ioc容器进行初始化
		this.contextLoader.initWebApplicationContext(event.getServletContext());
	}

IOC容器的初始化是由ContextLoader类执行:

org.springframework.web.context.ContextLoader

	public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
		// 是否已经加载IOC容器
		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(ContextLoader.class);
		servletContext.log("Initializing Spring root WebApplicationContext");
		if (logger.isInfoEnabled()) {
			logger.info("Root WebApplicationContext: initialization started");
		}
		long startTime = System.currentTimeMillis();

		try {
			// Store context in local instance variable, to guarantee that
			// it is available on ServletContext shutdown.
			if (this.context == null) {
				this.context = createWebApplicationContext(servletContext);
			}
			if (this.context instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
				if (!cwac.isActive()) {
					// The context has not yet been refreshed -> provide services such as
					// setting the parent context, setting the application context id, etc
					if (cwac.getParent() == null) {
						// The context instance was injected without an explicit parent ->
						// determine parent for root web application context, if any.
						ApplicationContext parent = loadParentContext(servletContext);
						cwac.setParent(parent);
					}
					// 此方法是刷新初始化IOC容器的地方
					configureAndRefreshWebApplicationContext(cwac, servletContext);
				}
			}
			// IOC容器加载后,将IOC容器保存于ServletContext容器中
			servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

		...
	}

熟悉的refresh()方法的调用:

org.springframework.web.context.ContextLoader  

	protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
		if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
			// The application context id is still set to its original default value
			// -> assign a more useful id based on available information
			String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
			if (idParam != null) {
				wac.setId(idParam);
			}
			else {
				// Generate default id...
				if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
					// Servlet <= 2.4: resort to name specified in web.xml, if any.
					wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
							ObjectUtils.getDisplayString(sc.getServletContextName()));
				}
				else {
					wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
							ObjectUtils.getDisplayString(sc.getContextPath()));
				}
			}
		}

		wac.setServletContext(sc);
		String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
		if (initParameter != null) {
			wac.setConfigLocation(initParameter);
		}
		customizeContext(sc, wac);

		// 熟悉的refresh()对Spring IOC容器进行加载,接下来的步骤就是 "自我分析-Spring IOC"文脏中的内容
		wac.refresh();
	}

Spring IOC销毁

对Spring IOC容器和其他Spring环境信息进行销毁:

org.springframework.web.context.ContextLoaderListener

	public void contextDestroyed(ServletContextEvent event) {
		if (this.contextLoader != null) {
			this.contextLoader.closeWebApplicationContext(event.getServletContext());
		}
		ContextCleanupListener.cleanupAttributes(event.getServletContext());
	}

具体清理销毁了spring的什么东西,自己再跟踪下代码即可。

若文中存在分析错误,望留言指出,在此非常感谢。

时间: 2024-10-02 17:37:33

自我分析-Spring IOC在Web应用的启动和销毁的相关文章

自我分析-Spring IOC

Spring IOC容器实现原理大致是容器(Map)+反射(Java反射和cglib).Spring提供丰富的ApplicationContext,以FileSystemXmlApplicationContext来分析IOC容器. 代码中大量使用设计模式-模板模式,若不清楚请先看看模板模式再来看具体分析.分析框架代码时要 多使用查看类继承和调用关系快捷键,快捷键可以设置,我是设置为F1和F4. 注意: 1.本文重在怎么自我分析框架代码,所以对其中解析需自己实际跟踪代码实践方可. 2.spring

自我分析-Spring AOP

Spring AOP直白的来说就是使用了JDK的动态代理和CGLIB对Bean的代理,从而实现方法增强的效果. 注意: 1.分析框架代码时,要常使用类继承.调用关系等快捷键,可以更高效的学习,快捷键可以设置成你习惯的按键: 2.本文重在怎么自我分析框架代码,所以对其中解析需自己实际跟踪代码实践方可: 3.spring源代码版本 spring-framework-3.2.1.RELEASE. 预览 org.springframework.beans.factory.support.Abstract

Spring IoC 依赖注入(二)源码分析

目录 Spring IoC 依赖注入(二)源码分析 1. 依赖注入口 - populateBean 1.1 doCreateBean 1.2 populateBean 2. 手动注入 2.1 相关的类说明 2.2 applyPropertyValues 2.3 BeanDefinitionValueResolver 2.4 依赖检查 2. 自动注入 2.1 那些字段会自动注入 2.2 名称注入 2.3 类型注入 Spring IoC 依赖注入(二)源码分析 本章主要分析 Spring IoC 依

Spring:源码解读Spring IOC原理

Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器的初始化 1. XmlBeanFactory(屌丝IOC)的整个流程 2. FileSystemXmlApplicationContext 的IOC容器流程 1.高富帅IOC解剖 2. 设置资源加载器和资源定位 3.AbstractApplicationContext的refresh函数载入

Spring?IOC设计原理解析:本文乃学习整理参考而来

Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器的初始化 1. XmlBeanFactory(屌丝IOC)的整个流程 2. FileSystemXmlApplicationContext 的IOC容器流程 1.高富帅IOC解剖 2. 设置资源加载器和资源定位 3.AbstractApplicationContext的refresh函数载入

Spring:源码解读Spring IOC原理--(转载)

转自:http://www.cnblogs.com/ITtangtang/p/3978349.html 这篇文章个人觉得整理的很不错,很值得学习,为了方便自己学习和大家学习,特转载此文保留.请尊重原创~~ Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器的初始化 1. XmlBeanFactory(屌丝IOC)的整个流程 2. FileS

Spring IOC原理解读 面试必读

Spring IOC设计原理解析:本文乃学习整理参考而来 一. 什么是Ioc/DI? 二. Spring IOC体系结构 (1) BeanFactory (2) BeanDefinition 三. IoC容器的初始化 1. XmlBeanFactory(屌丝IOC)的整个流程 2. FileSystemXmlApplicationContext 的IOC容器流程 1.高富帅IOC解剖 2. 设置资源加载器和资源定位 3.AbstractApplicationContext的refresh函数载入

Spring IOC 源码简单分析 04 - bean的初始化

### 准备 ## 目标 了解 Spring 如何初始化 bean 实例 ##测试代码 gordon.study.spring.ioc.IOC04_Initialization.java public class IOC04_Initialization { public static void main(String[] args) { Resource resource = new ClassPathResource("ioc/ioc04.xml"); DefaultListabl

spring IOC源码分析(1)

1.何谓Spring IOC 何谓Spring IOC?书上谓之“依赖注入”,那何谓“依赖注入”? 作为一个Java程序猿,应该遇到过这样的问题,当你在代码中需要使用某个类提供的功能时,你首先需要new一个对象,给它传递必要的参数,然后才能使用它提供的功能,最后释放对象占用的内存,当然了这个在Java不需要你自己去干了.这也就是说你需要自己去管理变量的整个生命周期,这在大型项目中是很糟糕的.现在好了,有了Spring IOC,这些事情都不需要你去做,你只需要告诉Spring你需要的变量实例,配置