2. 为什么需要BeanDefinitionRegistry? 如果BeanDefinitionRegistry不存在,Spring的某些核心功能会受到什么样的影响? -- in config2.xml --> <bean id="sampleBean" class="com.example.SampleBean<em>2</em>" /> 这里,sampleBean 在两个配置文件中都有定义 com.example.SampleBean1还是com.example.SampleBean2? 这就是所谓的“Bean定义不一致”问题。 调试点2:用getMergedBeanDefinition之后,控制台打印的 BeanDefinition 的类型变为了 RootBeanDefinition ,此时,我们从BeanFactory中获取了合并后的子 BeanDefinition的合并的源码分析 5.1 BeanDefinition合并过程时序图 5.2 BeanDefinition合并过程源码解读 这里讲一下前一篇没提到的BeanDefinition
> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256); 下面来对BeanDefinition接口进行分析。 BeanDefinition 首先来看一幅图,BeanDefinition接口的UML类图关系: ? 可以看到BeanDefinition接口继承了两个接口,这两个接口均为祖宗级接口。 ConfigurableBeanFactory.SCOPE_PROTOTYPE; int ROLE_APPLICATION = 0; int ROLE_SUPPORT = 1; int ROLE_INFRASTRUCTURE = 2; 既然两者都可以存储bean对象,为啥是用BeanDefinition而不是Object呢? 本文介绍了Spring IOC容器中一个非常重要的接口BeanDefinition,以及解释了为啥beanDefinitionMap中存储的是BeanDefinition。
前面在讲到bean的生命周期时,提到了beandefinition,这个东西是用来创建bean对象的,beandefinition有很多重要属性:1.beanClass 2.scope 3.isLazy bean都得创建好 primary 如果找到了多个同type的bean,会查看有没有主bean,如果存在,则直接注入 initMethodName 初始化时对bean进行加工 beanfactory将利用beandefinition
他的作用就是通过标签找到相应的解析器解析成beanDefinition。 public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri org.springframework.beans.factory.xml.NamespaceHandler接口表明,这个接口可以读取节点信息并转换为BeanDefinition(BeanDefinition 2.1 如果子节点是<bean>元素,那就走普通的beanDefinition解析。 2.2 如果不是<bean>元素,那就走定制化beanDefinition解析。 ,向已有的BeanDefinitionRegistry中注册beanDefinition。
1 BeanDefinition的载入和解析 在完成对 BeanDefinition 的 Resource 定位之后,我们来了解整个 BeanDefinition 信息的载入过程.对IoC容器来说, 载入过程相当于把定义的 BeanDefinition 在IoC容器中转化为一个Spring内部表示的数据结构的过程.IoC容器对Bean的管理和依赖注入功能的实现,是通过对其持有的BeanDefinition 图1.2 对IoC容器执行refresh的过程 2 BeanDefinition在IoC容器中的注册 BeanDefinition 在IoC容器中完成了载入和解析后,用户定义的 BeanDefinition 图2.1 DefaultListableBeanFactory中用于持有BeanDefinition的ConcurrentHashMap 将解析得到的 BeanDefinition 向IoC容器中的 图2.2 注册的调用过程 BeanDefinition 注册的实现 ? 图2.3 用于BeanDefinition注册的registerBeanDefinition方法(上) ?
这就是 Spring BeanDefinition 中的父子关系问题。 2. 源码分析 那么接下来我们也把这块的源码稍微来分析一下。 BeanDefinition,就是将 child 中的属性和 parent 中的属性进行合并,然后返回,这个方法中有一个名为 mbd 的变量,这就是合并之后的结果。 如果 bd.getParentName() 不为空,则意味着存在 parent BeanDefinition,所以就要进行合并处理了,合并时候又有一个小细节,如果 parentBeanName 等于当前的 有了 pbd 之后,接下来 new 一个 RootBeanDefinition,然后调用 overrideFrom 方法进行属性合并,合并的方式就是用传入的 BeanDefinition 中的属性去覆盖 核心流程就是上面这个步骤,如此之后,拿到手的就是和 parent 合并之后的 BeanDefinition 了。 3.
前面松哥写文章和小伙伴们仔细捋了捋 Spring 中的 BeanDefinition 存在的几种情况,那么 BeanDefinition 是谁来加载呢? 如果是 Java 代码配置,那不用说,都是注解扫描去加载 BeanDefinition 的,但是如果是 XML 或者其他格式的配置文件,则有专门的 BeanDefinition 加载器,今天咱们就来看看这个专门的 BeanDefinition 加载器。 2. beanName,集合的 value 则是 BeanDefinition 对象。
BeanDefinition 官方解释: BeanDefinition是Bean的定义,描述了一个Bean实例。它包含了描述一个Bean所需的最少接口方法。 我的理解: 通过解析xml的<bean>节点,或者解析注解类,会将Bean的定义设置到BeanDefinition。但仅仅是BeanDefinition各种成员变量的设置,还没有实例化对象。 换句话说,对于xml解析法,只是把xml的<bean>文本转换为BeanDefinition对象而已;对于注解法,只是把注解的类转换为BeanDefinition对象而已。 BeanDefinitionHolder其实就是BeanDefinition加上beanName和一些别名。BeanDefinition本身包含了Bean的定义,但没包含beanName和别名。 对半成品的BeanDefinition进行加工处理,将以占位符表示的配置解析为最终的实际值,这样半成品的BeanDefinition就成为成品的BeanDefinition。
Web核心-Servlet Spring源码系列:启动过程 Spring源码系列:容器刷新 Spring源码系列:BeanFactory的创建 Spring源码系列:BeanDefinition源码解析 Spring源码系列:BeanDefinition载入(上) Spring源码系列:BeanDefinition载入(中) Spring源码系列:BeanDefinition载入(下) 上一篇是将Bean DefaultBeanDefinitionDocumentReader.parseDefaultElement 2. ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } //异常2: public void parsePropertyElements(Element beanEle, BeanDefinition bd) { //获取子元素节点 NodeList nl
依赖来源、配置元信息、容器、应用上下文以及Spring IoC 容器生命周期进行主要分析与概述 接下来的部分进入Spring Bean 的基础部分、我主要分析罗列了主要内容:定义Spring Bean、BeanDefinition 对定义Bean 的理解,什么事BeanDefinition? 那么定义Spring Bean 从一下几个方面进行深入讨论 首先第一个是什么是BeanDefinition:BeanDefinition其实字面意思它就是Bean的一个定义 ? 这个时候它的Bean可能就会包含一些大小相关的属性 总结 通过上述的维度,简单讨论了什么事Bean的定义以及如何来定义Bean,接下来主要分析BeanDefinition相关的元信息详细介绍一些案例的输出
Spring使用BeanDefinition来描述bean。 BeanDefinition ? BeanDefinition BeanDefinition继承了AttributeAccessor和BeanMetadataElement接口。 BeanDefinition接口是Spring对bean的抽象。 link org.springframework.beans.factory.parsing.ComponentDefinition}. */ int ROLE_INFRASTRUCTURE = 2; 继承了BeanDefinition,拓展了BeanDefinition接口的能力: ?
首先就是BeanDefinition的类定义: public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement (这个密等下揭开) 先来看看BeanDefinition一个继承结构吧(均是与BeanDefinition有直接关联的类或者接口)! int ROLE_SUPPORT = 1; ROLE_INFRASTRUCTURE = 2就是我这Bean是Spring自己的,和你用户没有一毛钱关系。 //这个提示用于注册完全是ComponentDefinition内部工作的一部分的bean int ROLE_INFRASTRUCTURE = 2; 上面是BeanDifinition的一些基本属性信息 void setParentName(String parentName); //如果父类存在,则返回当前Bean的父类的名称 String getParentName(); 2.当前Bean的className
继上一篇BeanFactory的创建之后,其实就是BeanDefinition载入了。 //只能通过绝对URL加载单个资源 Resource resource = resourceLoader.getResource(location); //解析并返回beanDefinition的数量 BeanDefinitionParserDelegate用于将 Document 的内容转成 BeanDefinition实例;BeanDefinitionDocumentReader 本身不具备该功能而是交给了该类来完成 这个在后面的说道BeanDefinition体系的时候再聊。 关于DefaultListableBeanFactory中registerBeanDefinition方法的解析逻辑将在[Spring源码系列:BeanDefinition载入(下)]()中来说.
1、beanDefinition类型判断和验证 这里的验证主要是验证不能将静态工厂方法与方法重写相结合(静态工厂方法必须创建实例); if (beanDefinition instanceof AbstractBeanDefinition beanName,"Validation of bean definition failed", ex); } } 2、尝试从beanDefinitionMap中获取老的bean 这里就是先根据 中已经存在名为beanName的Beandefinition 如果当前beanDefinitionMap中已经存在名为beanName的Beandefinition了(即检查是否有相同名称的beanDefinition 2:如果是单例模式的bean对象则Set中包含该beanName,执行到这里说明该BeanDefinition已经从一个单例模式的bean变为了一个普通的bean,所以缓存也需要更新。 protected void resetBeanDefinition(String beanName) { // 如果已经创建,则删除给定bean的合并bean定义。
package top.buukle.buukle.排序类; import java.util.Arrays; public class 合并数组 { //以数组 intervals 表示若干个区间的集合 请你合并所有重叠的区间,并返 //回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。 :区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. // // // 示例 2: // // //输入:intervals = [[1,4],[4,5]] //输出:[[1,5]] -> v1[0] -v2[0]); // 初始化结果数组 int[][] res = new int[intervals.length][2]; [++index] = interval; } // 如果 当前遍历节点左侧值小于结果集的当前索引右侧值,则为重合数组,择大的右侧值进行合并
同时为我们1.7小节中BeanDefinition的合并做一些铺垫 1.BeanDefinition继承的接口 2.AbstractBeanDefinition AbstractBeanDefinition BeanDefinition的方法分析 这里对于每个字段我只保留了一个方法,只要知道了字段的含义,方法的含义我们自然就知道了 // 获取父BeanDefinition,主要用于合并,下节中会详细分析 String 2.AbstractBeanDefinition AbstractBeanDefinition的继承关系 先看一下类图: ? 在合并BeanDefinition返回的都是RootBeanDefinition 我们通过@Bean注解配置的bean,解析出来的BeanDefinition都是RootBeanDefinition(实际上是其子类 总结 至此,我们算完成了BeanDefinition部分的学习,在下一节中,我将继续跟大家一起学习BeanDefinition合并的相关知识。
文章目录 BeanDefinition的注册顺序 DeffredImportSelector ? ---- BeanDefinition的注册顺序 首先是 @ComponentScan扫描: @Component @Service @Controller @Import的 @Component @Service
同时为我们1.7小节中BeanDefinition的合并做一些铺垫 BeanDefinition是什么? BeanDefinition的方法分析: 这里对于每个字段我只保留了一个方法,只要知道了字段的含义,方法的含义我们自然就知道了 // 获取父BeanDefinition,主要用于合并,下节中会详细分析 int ROLE_APPLICATION = 0; // 某些复杂的配置 int ROLE_SUPPORT = 1; // 完全内部使用 int ROLE_INFRASTRUCTURE = 2; 在合并BeanDefinition返回的都是RootBeanDefinition 我们通过@Bean注解配置的bean,解析出来的BeanDefinition都是RootBeanDefinition(实际上是其子类 总结: 至此,我们算完成了BeanDefinition部分的学习,在下一节中,我将继续跟大家一起学习BeanDefinition合并的相关知识。
上篇文章已经对BeanDefinition做了一系列的介绍,这篇文章我们开始学习BeanDefinition合并的一些知识,完善我们整个BeanDefinition的体系,Spring在创建一个 bean时多次进行了BeanDefinition的合并,对这方面有所了解也是为以后阅读源码做准备。 的名称 String getParentName(); 上篇文章中说过,这几个属性跟BeanDefinition的合并相关,那么我先考虑一个问题,什么是合并呢? 合并的总结: 所以我们可以总结如下: 子BeanDefinition会从父BeanDefinition中继承没有的属性 这个过程中,子BeanDefinition中已经存在的属性不会被父BeanDefinition 我们可以思考一个问题,为什么这一步需要合并呢?大家可以带着这个问题继续往下看,在后文我会解释。 2、实例化 Spring在实例化一个对象也会进行bd的合并。
最近有空把Spring加载bean流程复习了一下,也乘机可以做个整理.首先还是看下入口代码,本文主要讲解析及注册BeanDefinition整体加载流程: ClassPathXmlApplicationContext 在DefaultListableBeanFactory类中的registerBeanDefinition方法内,注册了BeanDefinition信息: this.beanDefinitionMap.put (beanName, beanDefinition); DefaultListableBeanFactory是Spring Bean加载中的核心类,现在不分析加载过程中细节,后面的章节会剖析.