参考
- Spring源码解读(1)-IOC容器BeanDefinition的加载
- 游伯度的博客 他的博客的几篇文章都讲得不错
-
spring bean parent属性详解 parent属性只是指定了父子bean的关系,为了减少配置书写而存在的。对于多个有共同属性的bean,用一个父bean包含这些共同属性,然后让那些bean指定那个父bean,即可减少书写。因为父bean只是配置用的,所以尝试使用父bean,将会导致错误。
代码案例见spring中<bean>中parent标签的使用
BeanDefinition继承关系
如图:
红圈的五个类都值得分析一下。
BeanDefinition
官方解释:
BeanDefinition是Bean的定义,描述了一个Bean实例。它包含了描述一个Bean所需的最少接口方法。一个BeanDefinition会有属性值、构造器参数和其它更多信息(取决于具体实现)。
我的理解:
通过解析xml的<bean>节点,或者解析注解类,会将Bean的定义设置到BeanDefinition。但仅仅是BeanDefinition各种成员变量的设置,还没有实例化对象。
换句话说,对于xml解析法,只是把xml的<bean>文本转换为BeanDefinition对象而已;对于注解法,只是把注解的类转换为BeanDefinition对象而已。
常用的一般是GenericBeanDefinition和AnnotatedGenericBeanDefinition。
AbstractBeanDefinition
属性解析
Spring源码解析——AbstractBeanDefinition属性
BeanDefinitionHolder
public class BeanDefinitionHolder implements BeanMetadataElement {
private final BeanDefinition beanDefinition;
private final String beanName;
@Nullable
private final String[] aliases;
// ...
}
在解析出BeanDefinition后,会再度封装出BeanDefinitionHolder。
BeanDefinitionHolder其实就是BeanDefinition加上beanName和一些别名。BeanDefinition本身包含了Bean的定义,但没包含beanName和别名。
RootBeanDefinition
-
RootBeanDefinition是最常用地实现类,它对应一般性地< bean > 元素标签。我们知道,在配置文件中可以定义父< bean >和子< bean >,父< bean >用RootBeanDefiniton表示,子< bean >用ChildBeanDefinition表示,而没有父< bean >的< bean >则用RootBeanDefinition表示。AbstractBeanDefintion对二者共同的类信息进行抽象。
-
从spring2.5起,注册bean的首选是GenericBeanDefinition,GenericBeanDefinition允许动态的定义父bean(通过setParentName方法)。
创建BeanDefinition
创建BeanDefinition主要包括两个步骤:
- 利用BeanDefinitionReader读取承载配置信息的Resource,通过XML解析器解析配置信息的DOM对象,简单地每个< bean >生成对应地BeanDefinition对象。但是这里生成的BeanDefinition可能是半成品,因为在配置文件中,可能通过占位符变量引用外部属性文件的属性,这些占位符变量在这一步里还没有被解析出来;
- 利用容器中注册的BeanFatoryPostProcessor对半成品的BeanDefinition进行加工处理,将以占位符表示的配置解析为最终的实际值,这样半成品的BeanDefinition就成为成品的BeanDefinition。
Bean源码解析
- DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) 会解析<beans>节点
- DefaultBeanDefinitionDocumentReader.parseDefaultElement会解析<beans>的非自定义子节点
- BeanDefinitionParserDelegate.parseBeanDefinitionElement会解析<bean>节点
- 由SimpleAliasRegistry.aliasMap保存别名关系
- 由DefaultListableBeanFactory.beanDefinitionMap保存beanName-beanDefinition映射关系。
解析时会调用到BeanDefinitionReaderUtils.registerBeanDefinition:
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
在此注册BeanDefinition和别名。
网友评论