一、前言
通过前面大批量的工作,终于要到注册BeanDefinitionHolder这一步了.当然还是通过一下代码作为入口进行分析.
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析xml元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 装饰bean
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 注册bean到容器中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
// 发送事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
解析、装饰都已经记录了,解析来的重点就是BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
这句代码了.
二、分析
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 注册 bean
// Register bean definition under primary name.
// 获取 bean 的名称
String beanName = definitionHolder.getBeanName();
// 注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//注册 bean 的所有别名
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
- 通过bean的名称进行注册
- 通过bean的别名进行注册
BeanDefinitionRegistry
这个对象是通过XmlReaderContext
中获取的.
// XmlReaderContext
public final BeanDefinitionRegistry getRegistry() {
return this.reader.getRegistry();
}
而这个reader则是XmlBeanDefinitionReader
,registry
对象则通过XmlBeanDefinitionReader
的构造方法传入进来,实际上这个registry
对象就是XmlBeanFactory
或者说是DefaultListableBeanFactory
,因为这两个有继承关系.
2.1 registerBeanDefinition
// DefaultListableBeanFactory
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 校验 bean 的定义是否合法
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 从缓存中取出 BeanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// bean 已被注册过
if (existingDefinition != null) {
// 如果不允许重复注册则抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 放入到 map 中
// 覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 判断是否有创建中的bean
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
// 加锁
// 不能修改启动时的集合,需要重新创建一个集合
synchronized (this.beanDefinitionMap) {
// 放入map中
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 如果这个已经 bean 在存在 则移除
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
// 如果这个已经 bean 在存在 则移除
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//注册成功,如果是重复注册的则销毁之前注册的bean
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
这个阶段呢,bean都还没开始创建,都是在做解析,注册之类的事情,所以这里有一个判断看起来比较迷惑hasBeanCreationStarted
.或许后面才会知道这个判断条件有啥用吧.
- 验证
beanDefinition
是否合法
beanDefinitionMap
这个map集合中
4. 如果该beanDefinition
未被注册过,则添加映射到beanDefinitionMap
中去和beanDefinitionNames
集合中去.
5. 注册成功,如果是重复注册的则销毁之前注册的bean
2.2 registerAlias
// SimpleAliasRegistry
@Override
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
// 加锁 并发控制
synchronized (this.aliasMap) {
// 判断 bean 名称是否与别名相同,如果相同则忽略
if (alias.equals(name)) {
// 移除别名
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}
else {
// 判断别名是否已存在
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
// 如果别名对应的bean的名称与name相同则忽略
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
// 是否允许覆盖,如果不允许则报错
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
registeredName + "' with new target name '" + name + "'");
}
}
//检查是否有循环引用别名 例如:A-B C-B A-C
checkForAliasCircle(name, alias);
//映射别名和名称到map中
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
- 判断别名是否与bean名称是否相同
- 如果相同则移除别名
- 判断别名是否已经存在
- 如果不存在检查是否存在循环引用
- 映射别名
这里检测是否存在循环引用比较有意思,之前文章应该记录到了这块儿的逻辑.
三、小结
bean的解析与注册已经分析完了,接下来就是重头戏了,终于要看看 spring 是怎么根据BeanDefinition
来创建bean对象.