前言
Github:https://github.com/yihonglei/thinking-in-spring
在上一篇文章中,分析了BeanDefinition在IOC容器中载入和解析的过程。
在这些动作完成之后,用户定义的BeanDefinition信息已经在IOC容器内建立了自己的数据结构以及
相应的数据表示,但此时这些数据不能供IOC容器直接使用,需要在IOC容器中对这些BeanDefinition
数据进行注册。这个注册为IOC容器提供了更友好的使用方式,在DefaultListableBeanFactory中,
是通过一个HashMap来持有载入的BeanDefinition的,这个HashMap的定义如下:
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
下面分析BeanDefinition如何注册到HashMap的。
从上一篇文章的BeanDefinition()处理开始看看IOC容器如何注册BeanDefinition。
DefaultBeanDefinitionDocumentReader.processBeanDefinition()源码:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
/**
* BeanDefinitionHolder是对BeanDefinition对象的封装,封装了BeanDefinition、Bean的名字和别名。
* 用来完成想IOC容器注册。得到BeanDefinitionHolder就意味着是通过BeanDefinitionParserDelegate
* 对XML元素的信息按照Spring的Bean规则进行解析得到的。
*
*/
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 这里是向IOC容器注册解析得到的BeanDefinition的地方
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
// 在BeanDefinition向IOC容器注册以后,发送消息
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
BeanDefinition注册在BeanDefinitionReaderUtils.registerBeanDefinition()方法中完成。
BeanDefinitionReaderUtils.registerBeanDefinition()方法源码:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
// 根据定义的唯一的beanName注册Beandefinition
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);
}
}
}
注册registerBeanDefinition()方法的具体实现在BeanDefinitionRegistry接口的实现类DefaultListableBeanFactory
中来完成。
DefaultListableBeanFactory.registerBeanDefinition()方法源码:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// BeanName和BeanDefinition不能为空,否则停止注册
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
// 检查是否有相同名字的BeanDefinition已经在IOC容器中注册了,如果有同名的BeanDefinition,
// 但又不允许覆盖,就会抛出异常,否则覆盖BeanDefinition。
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 检查下容器是否进入了Bean的创建阶段,即是否同时创建了任何bean
if (hasBeanCreationStarted()) { // 已经创建了Bean,容器中已经有Bean了,是在启动注册阶段创建的。
// Cannot modify startup-time collection elements anymore (for stable iteration)
// 注册过程中需要线程同步,以保证数据一致性
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {// 正在启动注册阶段,容器这个时候还是空的。
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
// 重置所有已经注册过的BeanDefinition或单例模式的BeanDefinition的缓存
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
到这里完成了BeanDefinition的注册,就算完了IOC容器的初始化过程。此时,在使用的IOC容器
DefaultListableBeanFactory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经
可以被容器使用了,它们都在beanDefinitionMap里被检索和使用。容器的作用就是对这些信息
进行处理和维护。这些信息就是容器建立依赖反转的基础,有了这些基础数据,就可以进一步完成
依赖注入,下一篇讨论依赖注入的实现原理Bean的创建,Bean依赖注入。
参考文献
1、《Spring技术内幕》
2、《Spring实战》
3、Spring官网API
4、Spring源码