Spring Bean状态(转)

Spring-beans的核心实体是BeanDefinition和BeanFactory。前者映射咱们的定义,后者则是依据定义生产bean的工厂。 
beans概念模型 
上图是spring beans的静态结构图,更可能是偏重于bean解析,由于1. 理解了bean解析也就理解了一半spring扩展能力;2.BeanFactory的复杂不在于类之间的组织结构,而在于复杂的调用链路,也就不必是静态结构方面作过多说明。须要说明的是,这只是概念模型,并不彻底映射到类,由于spring的抽象层次过高,一个概念实体功能每每由多个类协同完成,画起来比较费劲,就相似BeanFactory,光搞清楚各个BeanFactory之间的关系就理得头痛,因此都尽量从概念层面说明。css

重要实体说明

  • DefaultListableBeanFactory是BeanDefintionRegistry的默认实现,它是个适配器,用于适配BeanFactory和BeanDefintionRegistry,工厂和定义经过它统一。它由ApplicationContext初始化,并被做为BeanDefinitionReader的registry。Reader对配置文档加载解析,生成definition并注册到registry–其实就是DefaultListableBeanFactory,这样工厂就拥有了类定义,bean初始化时也能够经过内部方法轻松获取到定义。
  • NamespaceHandlerResolver用于获取配置解析实体–NamespaceHandler。它和registry均内聚在上下文实体–ReaderContext中,parser内聚上下文从而能够间接访问handler和registry得到解析和注册的能力。

其余几个实体都比较直观便于理解,再也不一一赘述。spring

总体交互过程

BeanDefinitionReader是整个bean解析的聚合根,它由ApplicationContext建立,并将DefaultListableBeanFactory做为registry传递给它。 
定义解析交互过程 
BeanDefinitionReader建立文档读取实体–DocuemntReader用于加载解析,并在step3加载文档时建立上下文–ReaderContext传递给文档读取实体。上下文贯穿于整个解析过程始终,它在文档读取实体使用parser解析时也会被传入parser中。mvc

Parse过程是整个加载过程的核心,默认parser经过间接关联的识别器能够依据不一样配置节点进行parser切换,当读到非默认配置时,则切换到对应客户化parser解析。解析完成后再经过间接关联的registry进行注册,从而配置定义进入spring管理,待getBean时使用。app

客户化配置节点解析

客户化配置是spring很是重要的扩展点,spring强大的扩展能力有一半功能要归功于它,另外一半中的80%就是后面要介绍的大名鼎鼎的BeanPostProcessor。不只仅一些第三方扩展(例如开篇提到的dubbo)基于它,spring自己的不少模块也是基于它,例如spring-aop,spring-context等等,spring体系内除了默认的beans命名空间其他都基于它扩展的。jvm

NamespaceHandlerResolver由BeanDefinitionReader初始化,后者在第一次被访问时读取spring.handlers文件。.handlers文件定义namespace uri和对应处理类的映射关系。例如:spa

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler

上面的这行配置就是配置声明的解析类。代理

NamespaceHandlerResolver依据节点namespace得到NamespaceHandler,而后使用handler处理自定义配置节点。code

public interface NamespaceHandler { void init(); BeanDefinition parse(Element element, ParserContext parserContext); BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext); }

init方法注册localName和自定义parser的关系,parser和localName的关系由handler的提供者本身注册。例如:继承

public void init() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); // Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); }

上面就是aop注册parser的代码片断。config,aspectj-autoproxy这些就是localName,parse过程当中不一样的localName会切换到不一样的parser解析。接口

spring先经过命名空间定位到handler,handler处理时再基于localName取相应的parser解析当前结点。好比这个配置,aop是命名空间,aspectj-autoproxy是localName。整个读取解析过程当中先经过aop找到AopNamespaceHandler,再在解析到aspectj-autoproxy节点时使用AspectJAutoProxyBeanDefinitionParser来解析。若是要研究spring源码,必定要先找到对应parser,知道每一个配置项对应到运行时的bean结构才能更好理解spring;并且parser可能会生成一些默认的BeanPostProcessor,若是意识不到这些后处理器,那么对代码的读取将会断片,陷入彻底没法理解的境地。好比spring-aop就是由parser默认生成AopAutoProxyCreator这个BeanPostProcessor,在bean初始化后由这个processor对bean生成代理。

Bean获取

getBeans 
上图是getBean过程,整个过程很简洁,实际深刻代码会发现很是繁琐。

BeanFactory和BeanDefinitionRegistry在spring里是统一的,参见第一节,图上为了方便理解,拆成两个概念实体。

须要注意的是第4步和第6步,bean配置时能够指定parent属性,若是有parent,则beanFactory会对local和parent作merge,merge的策略是对parent作覆盖,也能够理解为是对parent作继承。这和parent bean factory彻底是两个概念,必定要区分开。

在beans的实体静态结构里,分别注明了parent bean definition和parent bean factory。二者都是被关联的,而不是被继承。后者有点像jvm的双亲委托模型,parent和child有各自的上下文,相似于jvm的命名空间。parent bean factory由applicationContext设置,没法配置。好比spring mvc就是两个父子两个容器,在容器refresh时相应的也会把父容器的BeanFactory设置成子容器BeanFactory的parentBeanFactory。

spring bean状态

bean状态 
Bean主要通过instantiate,populate,initializeBean和registerDisposableBean4个状态,在状态流转中会调用不少spring预留的扩展接口。

    1. awareMethod 
      若是bean继承了BeanFactoryAware,BeanNameAware,BeanClassLoaderAware,则会在initialize阶段将BeanFactory, BeanName和bean ClassLoader设置给Bean。 
      注意它和ApplicationContextAware是不同的,后者是由BeanPostProcessor作后处理set的。

    2. init method init method不只仅包括配置的init-method方法还包括InitializedBean的afterPropertiesSet回调接口,这二者均是无参的,彻底能够互相替代,二者中afterPropertiesSet调用在前。

相关文章
相关标签/搜索