Spring容器分析

IoC Service Provider的职责:1.业务对象的构建管理;2.业务对象的依赖绑定;

1.Spring提供了两种容器类型:BeanFactory和ApplicationContext

  BeanFactory。基础类型IOC容器,提供完整的IOC服务支持。如果没有特殊指定,默认采用延迟初始化策略(lazy-load)。只有当客户端对象需要访问容器中的某个受管理对象的时候,才对该受管理的对象进行初始化以及依赖注入操作。所有,相对来说,容器启动初期速度较快,所需要的资源有限。对于资源有效,并且功能要求不是很严格的场景,BeanFactory是比较适合的IOC容器选择。
  ApplicationContext。ApplicationContext在BeanFactory的基础上构建,是相对比较高级的容器实现,除了拥有BeanFactory的所有支持,ApplicationContext还提供了其他高级特性,比如事件发布、国际化信息支持等。ApplicationContext所管理的对象,在该类型容器启动之后,默认全部初始化并绑定完成。所以,相对于BeanFactory来说,ApplicationContext要求的更多的资源,同时,因为启动时就完成所有初始化,容器启动时间较BeanFactory长。在那些系统资源充足,并且要求更多功能的场景中,ApplicationContext类型的容器是比较适合的选择。

    

ApplicationContext间接继承自BeanFactory,所以说它是构建与BeanFactory之上的IOC容器。

 

BeanFactory的对象注册与依赖绑定方式

1.直接编码方式

2.配置文件(properties或xml)

  <beans>作为所有<bean>的统帅,它拥有相应的属性对<bean>进行统一的默认行为配置,包括如下几个:

      default-lazy-init。其值可以指定为true或false,默认为false。用来标志是否对所有的<bean>进行延迟初始化。
      default-autowire。可以取值为no、byname、bytype、constructor以及autodetect。默认为no,如果使用自动绑定的话,用来标志全体bean使用哪一种默认绑定的方式。
      default-dependency-check。可以取值none、objects、simple以及all,默认值为none,即不做依赖检查。
      default-init-method。如果所管辖的<bean>按照某种规则,都有同样名称的初始化方法的话,可以在这里统一制定这个初始化方法名,而不用在每一个<bean>上都重复单独指定。
      default-destroy-method。与default-init-method想对象,如果所管辖的bean有按照某种规则使用了相同的对象销毁方法,可以通过这个属性统一指定。

  <bean>标签

  id属性-每个注册到容器的对象的唯一标志。class属性-class类型

  scope属性-singleton(单例)、prototype(实例)、

  request

    Spring容器,即XmlWebApplicationContext会为每个http请求创建一个全新的requestProcessor对象供当前请求使用,当请求结束后,该对象实例的生命周期结束  

  session、global session

3.注解

 

Spring容器启动过程

    基本上可以划分为两个阶段,即容器启动阶段和Bean实例化阶段;

    

  1.容器启动阶段

      容器启动伊始,首先会通过某种途径加载Configuration MetaData。除了代码方式比较直接,在大部分情况下,容器需要依赖某些工具类(BeanDefinitionReader)对加载的Configuration MetaData进行解析和分析,并将分析后的信息编组为相应的BeanDefinition,最后把这些保存了bean定义必要信息的BeanDefinition,注册到相应的BeanDefinitionRegistry,这样容器启动工作就完成了。

  总地来说,该阶段所做的工作可以认为是准备性的,重点更加侧重于对象管理信息的收集。当然,一些验证性或者辅助性的工作也可以在这个阶段完成。

  2.Bean实例化阶段
  经过第一阶段,现在所有的bean定义信息都通过BeanDefinition的方式注册到了BeanDefinitionRegistry中。当某个请求方通过容器的getBean方法明确地请求某个对象,或者依赖关系容器需要隐式地调用getBean方法时,就会触发第二阶段的活动。
  该阶段,容器会首先检查所请求的对象之前是否已经初始化。如果没有,则会根据注册的BeanDefinition所提供的信息实例化被请求对象,并未其注入依赖。如果该对象实现了某些回调接口,也会根据回调接口的要求来装配它,当该对象装配完毕之后,容器会立即将其返回请求方使用。如果说第一阶段只是根据图纸装配生产线的话,那么第二阶段就是使用转配好的生产线生产具体的产品了。

 

了解bean的一生
  容器启动之后,并不会马上就实例化相应的bean定义。我们知道,容器现在仅仅拥有所有对象的BeanDefinition来保存实例化阶段将要用的必要信息。只有当请求方通过BeanFactory的getBean()方法来请求某个对象实例的时候,才有可能触发Bean实例化阶段的活动。 BeanFactory的getBean方法可以被客户端对象显式调用,也可以在容器内部隐式地被调用。隐式调用有如下两种情况。
  对于BeanFactory来说,对象实例化默认采用延迟初始化。通常情况下,当对象A被请求而需要第一次实例化的时候,如果它所依赖的对象B之前同样没有被实例化,那么容器会先实例化对象A所依赖的对象。这时容器内部就会首先实例化对象B,以及对象 A依赖的其他还没有实例化的对象。这种情况是容器内部调用getBean(),对于本次请求的请求方是隐式的。
  ApplicationContext启动之后会实例化所有的bean定义,这个特性在本书中已经多次提到。但ApplicationContext在实现的过程中依然遵循Spring容器实现流程的两个阶段,只不过它会在启动阶段的活动完成之后,紧接着调用注册到该容器的所有bean定义的实例化方法getBean()。这就是为什么当你得ApplicationContext类型的容器引用时,容器内所有对象已经被全部实例化完成。不信你查一下类org.AbstractApplicationContext的refresh()方法。
之所以说getBean()方法是有可能触发Bean实例化阶段的活动,是因为只有当对应某个bean定义的getBean()方法第一次被调用时,不管是显式的还是隐式的,Bean实例化阶段的滑动才会被触发,第二次被调用则会直接返回容器缓存的第一次实例化完的对象实例(prototype类型bean除外)。当getBean()方法内部发现该bean定义之前还没有被实例化之后, 会通过createBean()方法来进行具体的对象实例化。

  

  1.Spring对bean进行实例化
  2.Spring将值和bean的引用注入到bean对应的属性中
  3.如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBean-Name()方法;
  4.如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;
  5.如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来;
  6.如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()方法;
  7.如果bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()方法。类似地,如果bean使用init-method声明了初始化方法,该方法也会被调用;
  8.如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessAfterInitialization()方法;
  9.此时,bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文环境中,直到该应用上下文被销毁。
  10.如果bean实现了DisposableBean接口,Spring将调用它的destroy()接口方法。同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。

 

posted @ 2018-04-02 19:59  做个安分守己的陈某某  阅读(162)  评论(0)    收藏  举报