Spring源码解读-Spring IoC容器初始化之资源注册

时间:2022-09-04 13:42:00

**上篇博客,讲到容器还没有发挥作用,需要注册,我们来看看注册吧。
这个过程是通过调用BeanDefinitionRegistry接口的实现来完成。这个注册过程将载入过程中解析得到的BeanDefinition向IoC容器进行注册。通过分析,在IoC容器内部将BeanDefinition注入到一个HashMap中去、IoC容器就是通过这个HashMap来持有这些BeanDefinition数据的。**

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

**将解析得到的BeanDefinition向IoC容器中的beanDefinitionMap注册的过程是在载入BeanDefinition完成后进行的,DefaultListableBeanFactory 实现了BeanDefinitionRegistry的接口,这个接口的实现完成BeanDefinition向容器的注册。
代码如下:**

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 {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//注册过程需要synchronized,保证数据的一致性
synchronized (this.beanDefinitionMap) {
//检查是不是又相同名字的BeanDefinition已经在ioc容器中注册了,如果有相同名字的,但
//不允许覆盖,那么会抛出异常
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
//正常注册BeanDefinition的过程,把Bean的名字存入到BeanDefinitionName的同时,把beanName作为map的key,把BeanDefinition作为value存入到容器持有的BeanDefinitionMap中
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}

resetBeanDefinition(beanName);
}

完成了注册,也就完成了IoC容器的初始化过程,这个时候,IoC容器DefaultListableBeanFactory中已经建立了整个bean的配置信息,而且这些BeanDefinition已经可以被容器使用了,都在beanDefinitionMap里被检索和使用。容器的作用就是对这些信息进行处理和维护。这些信息是容器建立依赖反转的基础,有了这些基础数据,我们才能依赖注入。后面会有依赖反转的博客。