`
dingchao.lonton
  • 浏览: 48671 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

spring源码分析之bean之IOC

阅读更多

最近在看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 源码分析(Bean的初始化)

    Spring 源码分析(Bean的初始化) 前言 本篇文章是个人第一次看spring源码并总结,同时也参考了下面这篇博客。基本也是按照他的思路来理解的。这也算是第一版个人简易理解。也算是窥见spring的冰山一角,之后也会...

    Spring源码解析4章150页+Spring3.2.4中文注释源码

    3、源码分析-IOC容器的初始化 4、源码分析-IOC容器的依赖注入 5、源码分析-IOC容器的高级特性 三阶段 Spring AOP的涉及原理及具体实践 SpringJDBC的涉及原理及二次开发 SpringMVC框架设计原理及手写实现 四阶段 ...

    深入解析Spring IoC源码:核心机制与实践应用

    本文深入探讨了Spring框架中IoC容器的源码机制,涵盖了容器的初始化、Bean工厂的实例化、Bean定义的读取及Spring Bean的生命周期管理。通过精细的分析,本文揭示了AnnotationConfigApplicationContext的实例化过程,...

    Spring IoC源码分析1

    1. bean的装配方式 1.表明当前类是一个配置类,是方法bean的源 2.将@Configuration配置的AppConfig的BeanDefinitio

    深入解析Spring IoC:源码与实践指南

    本文深入探讨了Spring IoC容器的加载过程及其源码实现,揭示了Spring中最为根本的概念之一。这包括从AnnotationConfigApplicationContext的实例化开始,到DefaultListableBeanFactory工厂的建立,再到...

    Spring AOP源码分析.mmap

    有关于Spring,我们最常用的两个功能就是IOC和AOP,前几篇文章从源码级别介绍了Spring容器如何为我们生成bean及bean之间的依赖关系 下面我们接着来看AOP的源码实现。 有关于AOP,我们在面试中也被无数次问到...

    xmljava系统源码-springframework-source-5.1.x:这是一个注释版的Spring源码分析工程,版本为5.1.x,

    微信搜索:'菜鸟封神记'公众号,定期分享Spring源码系列内容。 核心容器 spring-beans,spring-core: 这两个模块是Spring的核心模块,提供了IOC和DI的支持。 spring-context: 提供了Spring容器的支持,扩展了...

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

     第3章:讲解Spring IoC容器的知识,通过具体的实例详细地讲解IoC概念。同时,对Spring框架的三个最重要的框架级接口进行了剖析,并对Bean的生命周期进行讲解。  第4章:讲解如何在Spring配置文件中使用Spring 3.0...

    spring源代码解析

    //我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样,这个加载工程在容器的refresh()的时候启动。 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws...

    Spring技术内幕:深入解析Spring架构与设计原理(第2部分)

    你不仅能从木书中参透Spring框架的优秀架构和设计思想,而且还能从Spring优雅的实现源码中一窥Java语言的精髓。此外,《Spring技术内幕:深入解析Spring架构与设计原理》还展示了阅读源代码的卓越方法,不仅授你以鱼...

    Spring技术内幕:深入解析Spring架构与设计原理

    你不仅能从木书中参透spring框架的优秀架构和设计思想,而且还能从spring优雅的实现源码中一窥java语言的精髓。此外,本书还展示了阅读源代码的卓越方法,不仅授你以鱼,而且还授你以渔!..  如果你以一种淡定的...

    SPRING3技术内幕

    你不仅能从木书中参透Spring框架的优秀架构和设计思想,而且还能从Spring优雅的实现源码中一窥Java语言的精髓。此外,《Spring技术内幕:深入解析Spring架构与设计原理》还展示了阅读源代码的卓越方法,不仅授你以鱼...

    Spring技术内幕:深入解析Spring架构与设计原理 1/2

    你不仅能从木书中参透spring框架的优秀架构和设计思想,而且还能从spring优雅的实现源码中一窥java语言的精髓。此外,本书还展示了阅读源代码的卓越方法,不仅授你以鱼,而且还授你以渔!..  如果你以一种淡定的心态...

    《鲁班学院》子路老师spring底层原理分析视频全集.rar

    整个视频课程将由浅入深,介绍spring5源码的构建、spring5IOC容器的初始化过程、bean的声明周期过程、spring BeanFactoryPostporcessor并且结合原理给出当前流行的应用框架如何利用spring的源码知识写出优雅的代码,...

    Spring技术内幕:深入解析Spring架构与设计原理(第1部分)

    你不仅能从木书中参透Spring框架的优秀架构和设计思想,而且还能从Spring优雅的实现源码中一窥Java语言的精髓。此外,《Spring技术内幕:深入解析Spring架构与设计原理》还展示了阅读源代码的卓越方法,不仅授你以鱼...

    Spring技术内幕:深入解析Spring架构与设计原理(第一部分)

    你不仅能从木书中参透Spring框架的优秀架构和设计思想,而且还能从Spring优雅的实现源码中一窥Java语言的精髓。此外,《Spring技术内幕:深入解析Spring架构与设计原理》还展示了阅读源代码的卓越方法,不仅授你以鱼...

    spring-annotion:Spring源码分析以及注解开发

    Spring注解驱动开发,包含一个refresh()方法的流程(在resources目录下) 模块介绍 --->... config AOP IOC已经一些bean的流程配置模块--->启动也包含SpringMVC注解化开发和Servlet3.0注解开发

    Spring技术内幕:深入解析Spring架构与设计原理 2/2

    你不仅能从木书中参透spring框架的优秀架构和设计思想,而且还能从spring优雅的实现源码中一窥java语言的精髓。此外,本书还展示了阅读源代码的卓越方法,不仅授你以鱼,而且还授你以渔!..  如果你以一种淡定的...

    SPRING3技术内幕.z01

    你不仅能从木书中参透Spring框架的优秀架构和设计思想,而且还能从Spring优雅的实现源码中一窥Java语言的精髓。此外,《Spring技术内幕:深入解析Spring架构与设计原理》还展示了阅读源代码的卓越方法,不仅授你以鱼...

Global site tag (gtag.js) - Google Analytics