简单谈谈Spring的IoC

1、前言

  这几天正在复习Spring的相关内容,同时想要对Spring的实现原理作一些深刻的研究。今天看了看SpringIoC的实现,找到了一篇很是详细的博客,研究了一个下午,看完以后惟一的感觉就是——太复杂了。Spring源码中,类和接口的体系很是的复杂,同时方法的实现也是,方法调用感受无穷无尽,甚至相互调用,给我绕的晕晕的。应该是本身目前的技术水平还过低,项目经验也不足,甚至对Spring的运用都不够熟悉,因此研究源码对我来讲可能仍是太早了。java

  虽然对于SpringIoC,我可能连十分之一都尚未弄懂,可是一个下午的研究也不是毫无收获。这篇博客就来简单讲讲我对IoC的理解,以及Spring中,IoC最基本的实现流程。spring


2、正文

2.1 什么是IoC

  在咱们使用传统的编码方式编写代码时,若是在类中须要引用另一个类的对象,咱们通常会直接在类中使用new关键字,建立这样一个对象。此时,使用这个对象的类,就与这个对象所对应的类产生了耦合性。c#

  IoC中文名称为控制反转,它就是用来解决上述问题的一种设计思想,它能指导咱们设计出耦合性更低,更易于管理的代码。传统的程序,都是在须要使用的地方主动地建立对象,而IoC的思想倒是将建立对象的工做交给IoC容器去进行。咱们告诉IoC容器,它须要建立那些对象,IoC容器建立好这些对象,而后主动地将它们注入到须要使用的地方。此时,须要使用对象的那些类,并不主动地获取对象,并且由IoC容器为它们分配,控制权在IoC容器手上,这就是控制反转。固然,IoC容器并不仅是控制对象,能够理解为控制外部资源的获取oop

  IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找咱们,咱们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。post


2.2 IoC和DI的关系

  DI中文名称为依赖注入,它其实和IoC是相同的概念,或者能够理解为它是IoC的一种具体的实现方式。IoC的概念可能比较模糊,控制反转只是一种思想,可能仅仅只是停留在由其余组件控制对象,而不是在使用的地方直接建立这一层面,可是具体如何实现并无指明。而DI就是它的一种实现思路,由容器建立对象,并主动将对象注入到须要使用它的地方。2.1中对IoC的解释,实际上更加偏向于DI学习


2.3 Spring如何实现IoC

  这一块,我就简单地说一说我今天下午在研究SpringIoC源码的过程当中,了解到的一些内容。首先,SpringIoC容器,能够简单地理解为就是BeanFactory接口的一个实现类对象,好比Spring的应用上下文接口ApplicationContext就是继承自BeanFactory,而咱们使用较多的ClassPathXmlApplicationContext就是ApplicationContext的一个实现类。它们均可以理解为是SpringIoC容器,而BeanFactory就是这个继承体系中的最高层。下面我就以单例bean的建立,简单地说一说SpringIoC实现的一个过程,假设使用到的是ClassPathXmlApplicationContext这个容器,解析的是xml配置文件:编码

  1. 容器解析xml配置文件,将声明在xml文件中的bean的配置信息提取出来,每个bean的配置信息被封装成一个BeanDefinitionHolder对象。BeanDefinitionHolder主要包含三个成员——BeanDefinition对象,bean的名称(id),以及bean的别名。BeanDefinition对象就是用来保存一个bean的配置信息,好比bean的做用域,bean的类型,bean的依赖,bean的属性......
  2. 容器建立一个ConcurrentHashMap对象,这个mapkeybean的名称,而value则是BeanDefinition对象的引用。容器将第一步中解析出的每个BeanDefinitionHolder对象,它对应的bean名称,以及拥有的BeanDefinition引用放入这个map中。因此,这个map保存了咱们在程序中声明的全部的bean的配置信息。
  3. 容器初始化完成后,开始建立bean,遍历第二步中的map集合,获取到bean的名称以及对应的BeanDefinition对象,经过BeanDefinition对象中的信息,判断这个bean有没有定义为延迟加载,若没有,则须要如今就进行建立。在建立前,先经过BeanDefinition中的配置信息,判断此bean有没有depend-on(依赖)其余bean,如有,则先建立当前bean依赖的bean(此处的depend-on不是bean的属性,而是须要经过配置项进行配置的)。以后,则建立当前遍历到的bean
  4. bean在建立完成后,经过beanBeanDefinition对象,获取bean须要注入值的属性,而后为属性赋值,若属性的值类型是其余的bean,则以上面相同的步骤,建立属性对应的bean
  5. 容器建立一个ConcurrentHashMap,将建立好的单例bean保存在其中。咱们在代码中能够经过容器的getBean方法,传入bean的名称或类型获取单例bean。容器会先去这个map中查找,若map中不存在,且这个bean的配置在第2步中存储配置信息的map中可以找到,则建立这个bean,放入存储beanmap中(由于bean能够配置延迟加载,即第一次获取时加载);

  Spring中,bean最基本的两种做用域就是singleton(单例)和prototype(多例),默认为单例。以上过程是单例bean的建立过程,若做用域为prototype,则每一次调用getBean方法,都会建立一个新的bean。顺带一提,建立bean的方式是经过反射机制,这个大部分人应该都知道。prototype


3、总结

  以上内容是我根据本身的认识,对SpringIoC作的一次简单记录,内容并不全面,由于我目前对它的理解也比较浅显。在今天阅读Spring源码的过程当中,我发现它真的比我想象中要复杂不少,或许是我水平有限,又或许是没有掌握阅读源码的方法,读起来真的很是吃力。总而言之,想要真正读懂Spring,我还须要不少的学习,但愿从此可以尽快提高本身,早日将Spring吃透。设计


4、参考

相关文章
相关标签/搜索