---恢复内容开始---

前言

在上一篇中有一处代码是BeanDefiniton注册的入口,我们回顾一下。

1.BeanDefiniton在IOC容器注册

首先我们回顾两点,1. 发起注册的地方;2. 注册的实现类

1.发起注册的地方

我们先看第一点,在上篇博文中我们讲了Bean的解析,在DefaultBeanDefinitonDocumentReader类的processBeanDefiniton()方法中,其中一个是去完成BeanDefiniton的载入,另一个是完成注册。我们看下代码:

DefaultBeanDefinitionDocumentReader类的processBeanDefinition方法

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//解析方法
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 注册方法
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}

现在我们找到了BeanDefiniton的注册入口,我们知道BeanDefinitonHolder=BeanDefiniton+BeanName,来看下registerBeanDefinition的代码:
                     BeanDefinitionReaderUtils类的registerBeanDefinition方法

public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException { // 根据beanName注册BeanDefinition
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // 如果有别名,注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}

2 注册的实现类

我们找registerBeanDefinition的实现类,会发现有三个实现类,那么具体取哪个呢?还记得我们最初容器建立的时候用的什么容器吗?我们回顾下代码:

AbstractRefreshableApplicationContext类的refreshBeanFactory方法

protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

而且,我们看下DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,这个接口就是定义注册的。并且这个类中有这么一个HashMap,存放beandefiniton的地方。

//---------------------------------------------------------------------
// Implementation of BeanDefinitionRegistry interface
//--------------------------------------------------------------------- @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 {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
} BeanDefinition oldBeanDefinition; 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 {
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<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;
} if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

到这里,代码就完成了IOC容器的初始化过程。此时,在使用的IOC容器DefaultListableBeanFactory中已经建立了整个Bean的配置信息,而且这些BeanDefinition已经可以被容器使用了。他们都在beanDefinitionMap中被检索和使用。

---恢复内容结束---

Spring IOC容器的初始化-(三)BeanDefinition的注册的更多相关文章

  1. Spring IoC容器的初始化过程

    Spring IoC容器的初始化包括 BeanDefinition的Resource定位.载入和注册 这三个基本的过程.IoC容器的初始化过程不包含Bean依赖注入的实现.Bean依赖的注入一般会发生 ...

  2. Spring IOC容器的初始化-(二)BeanDefinition的载入和解析

    前言 1.在讲BeanDefinition的载入和解析之前,我们先来看看什么是BeanDefinition. Bean对象在Spring中是以BeanDefinition来描述的,也就是说在Sprin ...

  3. Spring IOC容器的初始化—(一)Resource定位

    前言 上一篇博文“ Spring IOC是怎样启动的 ”中提到了refresh()方法,这个就是容器初始化的入口.容器初始化共有三个阶段: 第一阶段:Resource定位 第二阶段:BeanDefin ...

  4. Spring IOC容器的初始化流程

    IOC初始化流程 Resource定位:指对BeanDefinition的资源定位过程.Bean 可能定义在XML中,或者是一个注解,或者是其他形式.这些都被用Resource来定位, 读取Resou ...

  5. spring5源码分析系列(三)——IOC容器的初始化(一)

    前言: IOC容器的初始化包括BeanDefinition的Resource定位.载入.注册三个基本过程. 本文以ApplicationContext为例讲解,XmlWebApplicationCon ...

  6. 03.Spring IoC 容器 - 初始化

    基本概念 Spring IoC 容器的初始化过程在监听器 ContextLoaderListener 类中定义. 具体由该类的的 configureAndRefreshWebApplicationCo ...

  7. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(6):Spring IOC容器学习(概念、作用、Bean生命周期)

    一.IOC控制反转概念 控制反转(IOC)是一种通过描述(在Java中可以是XML或者是注解)并通过第三方去生产或获取特定对象的方式. 主动创建模式,责任在于开发者,而在被动模式下,责任归于Ioc容器 ...

  8. Spring IOC容器分析(4) -- bean创建获取完整流程

    上节探讨了Spring IOC容器中getBean方法,下面我们将自行编写测试用例,深入跟踪分析bean对象创建过程. 测试环境创建 测试示例代码如下: package org.springframe ...

  9. 04.Spring Ioc 容器 - 刷新

    基本概念 Spring Ioc 容器被创建之后,接下来就是它的初始化过程了.该过程包含了配置.刷新两个步骤 . 刷新由 Spring 容器自己实现,具体发生在 ConfigurableApplicat ...

随机推荐

  1. 【WIN7】windows\system32 下的几乎所有文件的简单说明【2】

    1: System32的详解 C:\WINDOWS\system32... 2:   3: 这个 system32 文件夹中包含了大量的用于 Windows 的文件. 这里主要用于存储 DLL 文件, ...

  2. 20145229吴姗珊逆向BOF实践

    20145229吴姗珊逆向BOF实践 实践 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. ...

  3. sqlmap的简要使用方法

    仅作为备忘!!! sqlmap使用: 注入类型有四种分别为:boolean-based blind.error-based.stacked queries.inline query. sqlmap - ...

  4. python中set的用处

    python中有很多不同的数据结构,比如list,tuple,set,dic等,为什么我要单独讲set呢. 因为set是一个比较容易被遗忘的数据结构,不光在python中,在C++中也一样,反正我是很 ...

  5. 初涉Rx套餐 之RxBinding(让你的事件流程更清晰)

    转载请注明出处:王亟亟的大牛之路 最近下班回家都在WOW,周末就爆肝,感觉人都要GO DIE了,昨天下午看了看RxBinding相关的功能感觉还是蛮强大的,所提供的API也是相当丰富(基本Rx套餐都是 ...

  6. zabbix 安装配置

    zabbix的配置文件一般有三种:zabbixserver的配置文件      zabbix_server.confzabbixproxy的配置文件      zabbix_proxy.confzab ...

  7. java基础(3)--8种基本类型

    八种基本类型 数据类型分为两大类:基本类型,引用类型 基本类型有8种,除了基本类型(8种)以外任何类型都是引用类型.如: String 是引用类型 基本类型有8种(首字母是小写): 整数:byte, ...

  8. 第三篇:Spark SQL Catalyst源码分析之Analyzer

    /** Spark SQL源码分析系列文章*/ 前面几篇文章讲解了Spark SQL的核心执行流程和Spark SQL的Catalyst框架的Sql Parser是怎样接受用户输入sql,经过解析生成 ...

  9. Activity启动的四种方式

    Activity启动方式有四种,分别是: standardsingleTopsingleTasksingleInstance 可以根据实际的需求为Activity设置对应的启动模式,从而可以避免创建大 ...

  10. yii2: oracle汉字占用字节长度

    OCIStmtExecute: ORA-12899: value too large for column "WSG"."WX_ENTER_TASTE".&qu ...