`
j小虫
  • 浏览: 18864 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

spring源码学习(三)

    博客分类:
  • java
 
阅读更多

创建容器我们在(二)里仔细的学习过了,现在再看容器的configureAndRefreshWebApplicationContext,配置并且刷新,这一步是整个spring ioc的核心,点进去看

 

 

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

		// Determine parent for root web application context, if any.
		ApplicationContext parent = loadParentContext(sc);

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

 

 

我们可以看到,首先spring会为容器创建一个id,这个id花了一大段的代码,我们可以看到,id的来源可以是我们在web.xml中配置的,也可以是自动生成的,如果自动生成,则跟servlet版本有关,具体的逻辑有兴趣的可以仔细看看。

 

接下来,加载父容器,通常情况下我们只有一个applicationContext.xml时这个父容器的引用是null.

 

 

wac.setServletContext(sc);

 这一步,它将servletContext这个上下文放到了wac中,也就是说,在容器中,有了servlet的上下文参数,那么我们可以在spring后续的容器操作中,使用servlet的配置等信息了。

 

 

 

String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);

这里,去取web.xml里的配置信息了,就是我们在web.xml里配置的配置文件路径,我们看看

 

 

public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";

 

 

于是我们去web.xml里找contextConfigLocation,可以看到

 

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath*:spring/applicationcontext.xml,
			classpath*:spring/spring-*.xml,
			classpath*:spring/consumer/spring-*.xml,
			classpath*:spring/provider/spring-*.xml
			
		</param-value>
	</context-param>

 

 

 

我这里是配置了多个文件,整个是一个字符串,spring会获取他们并且set他们

 

if (initParameter != null) {
			wac.setConfigLocation(initParameter);
		}

 

 

 

 

我们看看

 

 

wac.setConfigLocation(initParameter);

 他的实现在哪里

 

 

 

 

首先,我们的容器是默认的xmlWebApplicationContext

 

public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {

 

 

 

然后

 

public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext
		implements ConfigurableWebApplicationContext, ThemeSource {

 

 

可以看到,他的爷爷类

AbstractRefreshableConfigApplicationContext

 

是一个抽象的,可配置的抽象容器

 

 

我们在看的过程中应该去思考,我们需要找到一些方法应该被spring放在什么地方,既然是配置信息,应该是放在可配置的容器中,而我们现在要找的是他的实现方法,所以应该是一个抽象类中,于是我们进到

AbstractRefreshableConfigApplicationContext中,ctrl+o,输入

 

setConfigLocation

 

 

接下来就能看到它怎么处理我们配置的那几个配置文件了

 

 

public void setConfigLocations(String[] locations) {
		if (locations != null) {
			Assert.noNullElements(locations, "Config locations must not be null");
			this.configLocations = new String[locations.length];
			for (int i = 0; i < locations.length; i++) {
				this.configLocations[i] = resolvePath(locations[i]).trim();
			}
		}
		else {
			this.configLocations = null;
		}
	}

 

 

 

可以看到它把配置放到了AbstractRefreshableConfigApplicationContext的一个成员数组configLocations中,这里先mark一下,因为这里它放进去,是为了后续取出来去加载bean用的,所以记牢

 

 

 

我们接着看容器的刷新

customizeContext(sc, wac);

 

 

这个方法,又可以顾名思义了,customize,自定义的。定制的。而且我百度上查过好像有人说早期版本的spring这个方法是空实现,那么我觉得应该这个地方应该是埋了个点,为了后续版本spring加入一些其他功能而打下的伏笔,再看这个方法的注释。

 

 

Customize the ConfigurableWebApplicationContext created by this ContextLoader after config locations have been supplied to the context but before the context is refreshed. 

The default implementation determines what (if any) context initializer classes have been specified through context init parameters and invokes each with the given web application context. 

Any ApplicationContextInitializers implementing Ordered or marked with @Order will be sorted appropriately.

 

 

 

在为容器设置了配置文件之后,并且在容器真正刷新之前,由contextLoader为容器进行一些定制操作

定制操作的默认的实现是去决定容器的初始化类,并且这些类是通过web.xml里的配置参数来决定的,它的执行依赖本容器。

 

任何初始化都实现Ordered或使用了@Order注解来排序

这里我没有太读懂排序是怎么排,排什么,断点到这里我的环境都是直接返回,看懂这块的朋友可以留言

 

 

好了,定制操作之后就是refresh了,

wac.refresh();

这个方法完成了spring 容器的刷新,我们点进去看下

 

 

可以看到,由很多步骤完成,每一步都值得我们细细的去看

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}
		}
	}

 

我们在接下来的(三),(四),(五)里,每一节就只学习一个步骤,一个方法,细细的看,慢慢的想

 

 

 

分享到:
评论

相关推荐

    Spring学习笔记&源码

    本资料“Spring学习笔记&源码”是基于网易云课堂黑马程序员的Spring四天精通课程,旨在帮助学习者深入理解和实践Spring框架。 笔记部分可能会涵盖以下内容: 1. **Spring概述**:介绍Spring框架的历史、特点和主要...

    Spring源码学习加注释,方便学习.zip

    spring源码中文注释方便学习,spring源码学习加注释。 spring源码中文注释方便学习,spring源码学习加注释。 spring源码中文注释方便学习,spring源码学习加注释。 spring源码中文...

    Spring高级源码学习笔记.zip

    总之,Spring源码学习是一个深化编程技能,理解设计模式,以及提高问题解决能力的过程。通过深入研究,程序员不仅可以优化自己的代码,还能更高效地利用Spring框架提供的功能,提升项目的可维护性和扩展性。

    spring源码学习之思维导图

    1、spring 的整体架构 2、spring的基本实现(xml的加载原理、标签解析、bean加载) 3、容器扩展 4、ioc和aop 5、事务 6、springmvc 7、dispatcherServlet

    spring 源码环境搭建

    "spring源码" 是指 Spring 框架的源代码。 部分内容解释 1. 下载 GitHub 客户端安装 下载 GitHub 客户端是因为 Spring 源码托管在 GitHub 上,所以我们需要下载 GitHub 客户端来 clone Spring 源码。安装成功后,...

    spring源码

    学习Spring源码有助于深入理解其内部工作原理,例如bean的生命周期管理、AOP的实现、以及MVC的请求处理流程。这将有助于开发者更高效地利用Spring框架,编写出高质量、高性能的Java应用。通过分析源码,开发者还可以...

    spring 源码中文注释

    Spring框架是Java开发中最广泛应用的轻量级框架之一,它以IoC(Inversion of Control,控制反转)和AOP...通过学习源码,我们可以更全面地掌握Spring框架,提升自己的技术水平,更好地应对各种复杂的软件开发挑战。

    spring源码注释中文

    Spring 源码注释中文版的提供,使得开发者能够更加深入地理解 Spring 的工作原理,无需经过复杂的编译过程,可以直接阅读源码注释来学习。 Spring 框架主要由以下几个关键模块组成: 1. **Core Container(核心...

    构建为eclipse项目的spring源码

    在Eclipse中构建Spring源码项目,可以帮助我们深入理解Spring的工作原理,从而更好地利用它来构建高效、可维护的Java应用。以下将详细阐述如何构建和探索Spring源码。 1. **获取源码** Spring源码可以从官方GitHub...

    Spring源码学习一:源码分析概述1

    Spring源码学习概述 Spring是Java生态系统中的一种流行的开源框架,由Rod Johnson创立于2003年。Spring框架的主要目标是使Java应用程序的开发变得更加简洁、灵活和可维护。Spring框架的核心思想是基于依赖注入...

    spring源码分析专题学习资源

    spring源码分析专题,源码分析视频,对spring的源码进行分析

    spring源码(注释+测试版)

    这份"spring源码(注释+测试版)"提供了Spring框架的源代码,带有注释和测试用例,对于开发者深入理解Spring的工作原理非常有帮助。 1. **spring-core**:这是Spring框架的基础模块,包含了核心的工具类和资源处理...

    struts+hibernate+spring源码学习:hr考勤管理系统.rar

    struts+hibernate+spring源码学习:hr考勤管理系统.rar

    idea+gradle构建spring源码环境.docx

    在本文中,我们将详细介绍如何使用 IDEA 和 Gradle 构建 Spring 源码环境,以便深入学习 Spring 源码。下面是具体的步骤和知识点总结。 一、下载 Spring 源码 下载 Spring 源码有两种方式:一种是直接下载 zip ...

    spring框架学习源码

    在这个"Spring框架学习源码"中,我们将会探讨以下几个关键知识点: 1. **SpringBoot**:SpringBoot简化了Spring应用程序的初始搭建以及开发过程。它内置了Tomcat服务器,提供了一种默认的配置,使得开发者可以快速...

    马士兵老师spring框架学习笔记

    马士兵老师是知名的Java教育专家,他的Spring框架学习笔记深入浅出,对于初学者和进阶者来说都是一份宝贵的资源。这份笔记涵盖了Spring的核心概念、配置、AOP(面向切面编程)、DI(依赖注入)等关键知识点。 1. **...

    spring 源码分析CHM

    摘自javaEye 学习spring 源码的必备资料. 多多下载

    spring源码报错缺失的两个包

    在Spring框架的开发和学习过程中,...对于Spring源码的深入学习,了解其内部的工作原理,包括AOP、IOC(Inversion of Control)容器以及对其他库如CGlib和Objenesis的使用,都能极大地提升我们的技能和解决问题的能力。

    Tom_深入分析Spring源码

    《Spring源码分析》这份资料深入探讨了Spring框架的核心机制,尤其聚焦于Spring5版本。Spring作为Java领域中最重要的轻量级应用框架之一,它的设计理念、实现方式以及工作原理对于任何想成为优秀Java开发者的人都至...

Global site tag (gtag.js) - Google Analytics