Spring源码初探-IOC(1)-Bean的初始化
2016-07-08 本文已影响628人
LNAmp
前言
对于一名Java码农来说,Spring真是太重要了。目前Spring的体系已经发展得非常壮大,其底层基石core,beans,context非常牢固。
spring 体系结构图Bean初始化
个人认为,Spring最原始或者最基础的功能是“容器”,帮你管理着一堆bean的生命周期,任你取用,要想更好的使用Spring,还是得了解Bean的整个生命周期,首先了解Bean的初始化过程。本文采用XML配置文件的方式管理bean,分析XmlBeanFactory对于XML文件的解析过程。废话不多说,先上图:
Spring XmlBeanFacotry解析XML过程(1).jpg上图给出了XmlBeanFactory将xml配置解析成BeanDefinition的过程,最上面给出的类是在解析过程中涉及到的,首先大致进行一个介绍:
- Resource:是spring对于资源的一种抽象,因为资源的来源可能很丰富,利于File,Class Path Resource,Url Resource等,进行统一封装,暴露出getInputStream进行统一读取解析
- Document:这个没啥好讲的,XML文档对象
- EncodedResource:封装了Resource,指定Resource的编码
- ReaderContext:Bean Definition解析过程中的上下文对象,封装了Resource、ProblemReporter、EventListener、SourceExtractor等
- Element:XML中的元素节点对象
- BeanDefinition:这个接口及其实现类非常重要,他描述了XML中一个bean节点及其子节点的所有属性,将xml中的描述转变成内部的field信息,举例:scope,lazyinit,ConstructorArgumentValues(描述构造器),PropertyValues(描述属性值)等,是一个保罗万象的接口,其子类实现包括GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition等
- BeanDefinitionHolder:顾名思义包含了一个BeanDefinition,同时其包含了beanName和aliases,更好的封装了一次
- BeanDefinitionReader:定义了读取BeanDefinition的接口,主要作用是从Resource中读取Bean定义,XmlBeanDefinitionReader是其具体的实现类
- BeanDefinitionDocumentReader:定义了从Document对象中解析BeanDefinition并且注册到Registry中设计到的接口,其默认实现类是DefaultBeanDefinitionDocumentReader,主要是被XmlBeanDefinitionReader委派去处理Document对象
- BeanDefinitionParserDelegate:看到Delegate就知道这个哥们是个受苦的对象,是个最终干活的人,官方定义是“Stateful delegate class used to parse XML bean definitions.* Intended for use by both the main parser and any extension* {@link BeanDefinitionParser BeanDefinitionParsers} or* {@link BeanDefinitionDecorator BeanDefinitionDecorators}.”是用于最终处理XML bean定义的人,它做的可都是脏活累活,import/alias/bean等element以及element的子节点以及属性都是它解析并且填充到BeanDefinition中然后使用ReaderContext中的Registry(实际就是DefaultListableBeanFactory)来将该BeanDefinition注册
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); }
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); }
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); }
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); }}
上述代码描述了BeanDefinitionParserDelegate对于不同element的解析,脏活累活中非常的一个部分
小结
本文算是小小地总结了一下将XML解析成BeanDefinition的过程中涉及到的一些类,将XML解析出来其实是一个很简单的过程,但是Spring却用了非常多的类。究其原因还是为了考虑扩展性,不断地抽象,不断地将责任委派。这篇文章只介绍了DefaultElement的解析,下篇文章将介绍怎么自定义标签以及Spring怎么解析自定义标签。