最近在看spring的源码,正好把其记录下来
一 。 启动过程
在Web服务器tomcat(应用的容器)启动的时候的时候,首先web.xml会自动的加载到容器tomcat里面,所以我们会在web.xml里面加载spring的配置文件,是通过org.springframework.web.context.ContextLoaderListener或者org.springframework.web.context.ContextLoaderServlet加载我们的spring配置文件,我们就拿ContextLoaderListener为例子吧
在ContextLoaderListener这个类中,其实是调用的ContextLoader的initWebApplicationContext
方法,而在
initWebApplicationContext
调用createWebApplicationContext
来创建一个context
/* */ protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent)
/* */ throws BeansException
/* */ {
/* 230 */ Class contextClass = determineContextClass(servletContext);
/* 231 */ if (!(ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass))) {
/* 232 */ throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
/* */ }
/* */
/* 236 */ ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
/* */
/* 238 */ wac.setParent(parent);
/* 239 */ wac.setServletContext(servletContext);
/* 240 */ String configLocation = servletContext.getInitParameter("contextConfigLocation");
/* 241 */ if (configLocation != null) {
/* 242 */ wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation, ",; \t\n"));
/* */ }
/* */
/* 246 */ wac.refresh();
/* 247 */ return wac;
/* */ }
我们会注意到这个createWebApplicationContext
方法里面有一个有一个wac.refresh()方法,这个方法很重要,作用主要是对context进行更新,加载xml的spring配置文件到spring的容器的缓存中
在org.springframework.context.support.AbstractApplicationContext
中我们可以找到这个refresh方法的具体实现
/* */ public synchronized void refresh() throws BeansException, IllegalStateException
/* */ {
/* 275 */ this.startupTime = System.currentTimeMillis();
/* */
/* 278 */ refreshBeanFactory();
/* 279 */ ConfigurableListableBeanFactory beanFactory = getBeanFactory();
/* */
/* 282 */ beanFactory.setBeanClassLoader(getClassLoader());
/* */
/* 285 */ beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
/* */
/* 288 */ beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
/* 289 */ beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
/* 290 */ beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
/* 291 */ beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
/* 292 */ beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
/* */
/* 295 */ postProcessBeanFactory(beanFactory);
/* */
/* 298 */ for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext(); ) {
/* 299 */ BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor)it.next();
/* 300 */ factoryProcessor.postProcessBeanFactory(beanFactory);
/* */ }
/* */
/* 303 */ if (this.logger.isInfoEnabled()) {
/* 304 */ if (getBeanDefinitionCount() == 0) {
/* 305 */ this.logger.info("No beans defined in application context [" + getDisplayName() + "]");
/* */ }
/* */ else {
/* 308 */ this.logger.info(getBeanDefinitionCount() + " beans defined in application context [" + getDisplayName() + "]");
/* */ }
/* */ }
/* */
/* */ try
/* */ {
/* 314 */ invokeBeanFactoryPostProcessors();
/* */
/* 317 */ registerBeanPostProcessors();
/* */
/* 320 */ initMessageSource();
/* */
/* 323 */ initApplicationEventMulticaster();
/* */
/* 326 */ onRefresh();
/* */
/* 329 */ registerListeners();
/* */
/* 332 */ beanFactory.preInstantiateSingletons();
/* */
/* 335 */ publishEvent(new ContextRefreshedEvent(this));
/* */
/* 337 */ this.active = true;
/* */ }
/* */ catch (BeansException ex)
/* */ {
/* 342 */ beanFactory.destroySingletons();
/* 343 */ throw ex;
/* */ }
/* */ }
在refresh方法中,refreshBeanFactory();
这个方法的实现在 org.springframework.context.support.AbstractRefreshableApplicationContext
中,
protected final synchronized void refreshBeanFactory()
/* */ throws BeansException
/* */ {
/* 81 */ if (this.beanFactory != null) {
/* 82 */ this.beanFactory.destroySingletons();
/* 83 */ this.beanFactory = null;
/* */ }
/* */
/* */ try
/* */ {
/* 88 */ DefaultListableBeanFactory beanFactory = createBeanFactory();
/* 89 */ loadBeanDefinitions(beanFactory);
/* 90 */ this.beanFactory = beanFactory;
/* 91 */ if (this.logger.isInfoEnabled())
/* 92 */ this.logger.info("Bean factory for application context [" + getDisplayName() + "]: " + beanFactory);
/* */ }
/* */ catch (IOException ex)
/* */ {
/* 96 */ throw new ApplicationContextException("I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
/* */ }
/* */ }
我们可以看到一个很显眼的方法叫做 loadBeanDefinitions(beanFactory);
他是做什么的呢,看他的名字我们就猜的出来他是做什么的,他就是load spring的配置文件到spring容器的内存中,由于时间的关系,我就不详细的往下写了,具体的及时将xml拆分一个一个的BeanDefinition
然后放到一个Map
中缓存起来。而这个时候Web服务器已经启动完成了,同时spring的容器也完成了spring配置文件的解析以及缓存过程。
二 。 依赖注入过程
用的spring的童鞋都知道,如何实例化一个bean吗,那就是
Object beanInstance = conext.getBean("beanName");
但是这个过程是怎么做到的呢,让我们继续分析代码,首先我们的xml已经缓存在spring容器的内存中了,这个时候我们要用了,首先我们看看getBean的实现吧,getBean的实现在 org.springframework.beans.factory.support.AbstractBeanFactory
中,
/* */ public Object getBean(String name, Class requiredType, Object[] args)
/* */ throws BeansException
/* */ {
/* 194 */ String beanName = transformedBeanName(name);
/* 195 */ Object bean = null;
/* */
/* 198 */ Object sharedInstance = null;
/* 199 */ synchronized (this.singletonCache) {
/* 200 */ sharedInstance = this.singletonCache.get(beanName);
/* */ }
/* 202 */ if (sharedInstance != null) {
/* 203 */ if (isSingletonCurrentlyInCreation(beanName)) {
/* 204 */ if (this.logger.isDebugEnabled()) {
/* 205 */ this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
/* */ }
/* */
/* */ }
/* 210 */ else if (this.logger.isDebugEnabled()) {
/* 211 */ this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
/* */ }
/* */
/* 214 */ bean = getObjectForBeanInstance(sharedInstance, name, true);
/* */ }
/* */ else
/* */ {
/* 220 */ if (isSingletonCurrentlyInCreation(beanName)) {
/* 221 */ throw new BeanCurrentlyInCreationException(beanName);
/* */ }
/* */
/* 225 */ if ((getParentBeanFactory() != null) && (!(containsBeanDefinition(beanName))))
/* */ {
/* 227 */ if (getParentBeanFactory() instanceof AbstractBeanFactory)
/* */ {
/* 229 */ return ((AbstractBeanFactory)getParentBeanFactory()).getBean(name, requiredType, args);
/* */ }
/* 231 */ if (args == null)
/* */ {
/* 233 */ return getParentBeanFactory().getBean(name, requiredType);
/* */ }
/* */
/* 236 */ throw new NoSuchBeanDefinitionException(beanName, "Cannot delegate to parent BeanFactory because it does not supported passed-in arguments");
/* */ }
/* */
/* 241 */ this.alreadyCreated.add(beanName);
/* 242 */ RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false);
/* 243 */ checkMergedBeanDefinition(mergedBeanDefinition, beanName, requiredType, args);
/* */
/* 246 */ if (mergedBeanDefinition.isSingleton()) {
/* 247 */ synchronized (this.singletonCache)
/* */ {
/* 249 */ sharedInstance = this.singletonCache.get(beanName);
/* 250 */ if (sharedInstance == null) {
/* 251 */ if (this.logger.isDebugEnabled()) {
/* 252 */ this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
/* */ }
/* 254 */ this.currentlyInCreation.add(beanName);
/* */ try {
/* 256 */ sharedInstance = createBean(beanName, mergedBeanDefinition, args);
/* 257 */ addSingleton(beanName, sharedInstance);
/* */ }
/* */ catch (BeansException ex)
/* */ {
/* 264 */ throw ex;
/* */ }
/* */ finally {
/* 267 */ this.currentlyInCreation.remove(beanName);
/* */ }
/* */ }
/* */ }
/* 271 */ bean = getObjectForBeanInstance(sharedInstance, name, true);
/* */ }
/* 274 */ else if (mergedBeanDefinition.isPrototype())
/* */ {
/* 276 */ Object prototypeInstance = createBean(beanName, mergedBeanDefinition, args);
/* 277 */ bean = getObjectForBeanInstance(prototypeInstance, name, false);
/* */ }
/* */ else
/* */ {
/* 281 */ String scopeName = mergedBeanDefinition.getScope();
/* 282 */ Scope scope = (Scope)this.scopes.get(scopeName);
/* 283 */ if (scope == null)
/* 284 */ throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
/* */ try
/* */ {
/* 287 */ Object scopedInstance = scope.get(beanName, new ObjectFactory(beanName, mergedBeanDefinition, args) { private final String val$beanName;
/* */ private final RootBeanDefinition val$mergedBeanDefinition;
/* */ private final Object[] val$args;
/* */
/* */ public Object getObject() throws BeansException { return AbstractBeanFactory.this.createBean(this.val$beanName, this.val$mergedBeanDefinition, this.val$args);
/* */ }
/* */ });
/* 292 */ bean = getObjectForBeanInstance(scopedInstance, name, false);
/* */ }
/* */ catch (IllegalStateException ex) {
/* 295 */ throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active", ex);
/* */ }
/* */ }
/* */
/* */ }
/* */
/* 301 */ if ((requiredType != null) && (!(requiredType.isAssignableFrom(bean.getClass())))) {
/* 302 */ throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
/* */ }
/* 304 */ return bean;
/* */ }
我们看见有一个行代码
RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false);
看名字貌似是根据beanName获取 一个BeanDefinition对象,我们继续跟踪下去
/* */ protected RootBeanDefinition getMergedBeanDefinition(String name, boolean includingAncestors)
/* */ throws BeansException
/* */ {
/* 769 */ String beanName = transformedBeanName(name);
/* */
/* 772 */ if ((includingAncestors) && (!(containsBeanDefinition(beanName))) && (getParentBeanFactory() instanceof AbstractBeanFactory))
/* */ {
/* 774 */ return ((AbstractBeanFactory)getParentBeanFactory()).getMergedBeanDefinition(beanName, true);
/* */ }
/* */
/* 778 */ return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
/* */ }
我们发现最后一句话,return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)
); 里面有个 getBeanDefinition(beanName),
但是这个方法是
/* */ protected abstract BeanDefinition getBeanDefinition(String paramString)
/* */ throws BeansException;
怎么是个抽象方法啊,怎么回事呢,别急,一般的情况下,这个方法肯定是由他子类实现的,我们先找到他在子类的实现
在 org.springframework.beans.factory.support.DefaultListableBeanFactory
找到了他的实现
/* */ public BeanDefinition getBeanDefinition(String beanName)
/* */ throws NoSuchBeanDefinitionException
/* */ {
/* 313 */ BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName);
/* 314 */ if (bd == null) {
/* 315 */ if (this.logger.isDebugEnabled()) {
/* 316 */ this.logger.debug("No bean named '" + beanName + "' found in " + toString());
/* */ }
/* 318 */ throw new NoSuchBeanDefinitionException(beanName);
/* */ }
/* 320 */ return bd;
/* */ }
额,原来如此,BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName);
原来是通过缓存读取的BeanDefinition啊,而这个缓存beanDefinitionMap
正是第一步缓存的结果
接下来就是通过反射机制依照 BeanDefinition的定义来实例化 Bean然后返回
分享到:
相关推荐
Spring 源码分析 Spring 框架是 Java 语言中最流行的开源框架之一,它提供了一个强大且灵活的基础设施来构建企业级应用程序。在 Spring 框架中,IOC 容器扮演着核心角色,本文将深入分析 Spring 源码,了解 IOC ...
### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...
- 可以通过在接口实现的构造器、接口方法中设置断点,使用调试器观察线程调用栈来分析Bean对象创建和管理的触发时机。 4. **源码学习技巧** - 定焦原则:抓主线,即以源码的主要脉络为学习目标,理解框架的架构和...
Spring 源代码分析系列涵盖了多个关键模块,包括事务处理、IoC容器、JDBC、MVC、AOP以及与Hibernate和Acegi安全框架的集成。以下是对这些知识点的详细阐述: 1. **Spring 事务处理**:Spring 提供了声明式事务管理...
本篇文章主要分析了Spring如何通过`ClassPathXmlApplicationContext`来启动和初始化Bean的过程。 首先,`ClassPathXmlApplicationContext`是Spring的一种ApplicationContext实现,用于从类路径下的XML配置文件加载...
通过对Spring IoC容器的理解和源码分析,我们可以深入了解到Spring框架是如何管理和控制应用对象的生命周期及依赖关系的。在实际开发中,了解Spring IoC容器的工作原理有助于更好地利用Spring框架,提高开发效率和...
Spring4 IOC(Inversion of Control,控制反转)是Spring框架的核心特性之一,它极大地简化了Java应用程序的开发。在这个示例源码中,我们可以深入理解并学习如何在实际项目中运用Spring的IOC容器来管理对象的生命...
Spring Ioc 源码分析系列--自动注入循环依赖的处理 本篇文章主要讲解了 Spring Ioc 源码分析系列中自动注入循环依赖的处理机制。循环依赖是 Spring 框架中一个经典的问题,也是面试中常被问到的问题。本篇文章将...
Spring 框架的核心特性之一是Inversion of Control(IoC),也被称为依赖注入(Dependency Injection,DI)。IoC使得应用程序中的对象不再负责创建和管理它们的依赖对象,而是将这个责任交给了一个外部的容器,即...
《Spring源码分析——BeanFactory》 在Java的IoC(Inversion of Control)和DI(Dependency Injection)领域,Spring框架扮演着至关重要的角色。BeanFactory是Spring的核心组件之一,它是容器的基石,负责管理应用...
以上只是Spring源码分析的部分内容,实际源码中还包括Spring的其他模块,如Spring Batch(批处理)、Spring Security(安全)、Spring Integration(集成)等。理解并掌握Spring源码,有助于我们更好地利用Spring...
### Spring源码分析知识点 #### 一、Spring框架概述 Spring框架是一个全面的企业级应用开发框架,它通过一系列模块化的组件来支持不同的应用场景和技术需求。Spring的核心价值在于提供了一种简洁的方式来解决企业...
【标题】"Java进阶之SpringIoC源码深度剖析共19页.pd" 提供的是一项关于Java开发中的高级主题,特别是针对Spring框架的依赖注入(Inversion of Control,IoC)部分的深入研究。Spring IoC是Spring框架的核心特性之一...
在本文中,我们将深入探讨Spring IOC的概念、工作原理,并通过源码分析来理解其实现方式。 首先,控制反转(IOC)是指将对象的创建和管理权限交由一个外部容器(即Spring容器)来负责,而不是由代码本身直接控制。...
《Spring5 源码分析(第 2 版)》是某Tom老师精心编写的深度解析文档,旨在帮助读者全面理解Spring5的核心机制和设计理念。Spring作为Java领域最为广泛应用的框架之一,其源码的深入理解对于开发者来说至关重要。这篇...
3、源码分析-IOC容器的初始化 4、源码分析-IOC容器的依赖注入 5、源码分析-IOC容器的高级特性 三阶段 Spring AOP的涉及原理及具体实践 SpringJDBC的涉及原理及二次开发 SpringMVC框架设计原理及手写实现 四阶段 ...
《Spring IOC容器实现分析》 在Java开发领域,Spring框架无疑是使用最为广泛的轻量级框架之一,其中的核心组件就是IOC(Inversion of Control)容器。本文将深入剖析Spring的IOC容器,理解其工作原理和重要功能,以...
《Spring源码分析》 Spring框架作为Java领域中不可或缺的一部分,其强大之处在于它提供了丰富的功能,包括依赖注入(Dependency Injection,简称DI)、面向切面编程(Aspect-Oriented Programming,简称AOP)、事务...
Spring源码深度解析第二版 Spring是一款广泛应用于Java企业级应用程序的开源框架,旨在简化Java应用程序的开发和部署。Spring框架的核心主要包括了IoC容器、AOP、MVC框架等模块。 第1章 Spring整体架构和环境搭建 ...
《Spring源码分析》 Spring框架作为Java领域最流行的开源框架之一,它的设计思想和实现方式一直是许多开发者深入研究的对象。这份"Spring源码分析"资料深入探讨了Spring的核心机制,帮助我们理解其背后的原理,从而...