Ioc容器的初始化过程
在上一篇中,我们已经分析过BeanDefinition在Ioc容器中的载入和解析过程,在经过以上步骤之后,用户所定义的BeanDefinition信息已经在IoC容器中建立起来自己的数据结构以及相应的数据表示,但是这些数据还是不能供IoC容器直接使用,我们需要将这些数据注册到IoC容器中。在DefaultListableBeanFactory中是通过一个ConcurrentHashMap来持有载入的BeanDefinition的。
在分析DefaultBeanDefinitionDocumentReader#registerBeanDefinitions方法的时候,这个方法是用来解析DOM定义的,其中通过调用doLoadBeanDefinitions方法进行在给定的根元素中注册每一个bean定义,那么注册的过程发生在什么地方呢?
registerBeanDefinitions —> parseBeanDefinitions—>parseDefaultElement—>processBeanDefinition
- processBeanDefinition
/**
* Process the given bean element, parsing the bean definition
and registering it with the registry.
处理给定的bean元素,解析bean定义并在注册表中注册
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
注册最终修饰的实例
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));
}
}
从源代码中我们可以发现,注册的过程发生在registerBeanDefinition中
/**
* Register the given bean definition with the given bean factory.
给指定的bean工厂中注册指定的bean定义
@param definitionHolder the bean definition including name and aliases
包含bean的name和别名
@param registry the bean factory to register with
使用这个给bean工厂进行注册
@throws BeanDefinitionStoreException if registration failed
*/
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);
}
}
}
用于BeanDefinitionRegister是一个接口继承自AliasRegister,所以我们需要寻找它的子类DefaultListableBeanFactory是如何实现注册功能的
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
//断言bean名称必须不为空
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//断言bean定义必须不为空
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
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 + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(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;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
以上这个方法就是DefaultListableBeanFactory具体的注册方法。
总结:
- AbstractApplicationContext的refresh()方法定义容器初始化的整个流程,是一个模板方法,具体实现由子类完成
- 由AbstractApplicationContext的子类AbstractRefreshableApplicationContext对容器进行重启,创建一个新的容器,DefaultListableBeanFactory。
- 由于BeanDefinition的资源形式不同(XML,注解),所以需要不同的子类去继承AbstractRefreshableApplicationContext,来完成资源的定位工作,如AbstractXMLApplicationContext
- AbstractXMLApplicationContext本身是没有对资源定位和解析的功能的,由它创建BeanDefinitionReader,对资源进行定位,加载工作。
- BeanDefinitionReader完成定位和加载。首先获取到resource,通过resource得到InputStream,根据InputStream得到Document。然后创建BeanDefinitionDocumentReader。
- BeanDefinitionDocumentReader完成对xml的解析,获取BeanDefinitionHolder。
- 最后BeanDefinitionDocumentReader委托DefaultListableBeanFactory完成定义的注册。