在spring源码中,会涉及到bean和beanDefinition这两个概念,接下来,说下什么是bean,什么是beanDefinition

class、beanDefinition、bean三者的关系

class是我们自己写的类,bean是spring经过自己的一系列处理之后。生成的,我们可以认为bean是spring容器中真正的成品,beanDefinition是对bean的一个描述信息,spring会根据beanDefinition去生成bean,所以三者的关系是:
spring首先将class转换为beanDefinition,然后再将beanDefinition转换为bean
我们通常说,spring可以通过自动扫描,完成bean的实例化,其实这里的自动扫描,是把class文件,通过扫描,转换为beanDefinition

beanDefinition的定义

我们可以看下beanDefinition的定义

可以看到,一个beanDefinition中,定义了N多个属性和方法,比如:是否是primary、是否是懒加载、dependOn属性、autowireMode自动注入属性等

所以,我们可以简单的认为,spring在扫描class的时候,会根据class文件中的注解等信息,给beanDefinition对象赋值,所以,beanDefinition是对一个类的描述
那spring在真正去初始化、实例化一个bean的时候,直接根据beanDefinition去初始化就可以,比如,在判断这个bean是根据类型注入,还是根据名字注入的时候,就直接判断autowireMode的属性值即可

spring根据beanDefinition进行初始化

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons@Override
public void preInstantiateSingletons() throws BeansException {if (logger.isDebugEnabled()) {logger.debug("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.// 1.获取到所有的beanDefinitionNameList<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...// 2.依次遍历所有的beanDefinitionName,进行初始化for (String beanName : beanNames) {// 3.在mergedBeanDefinition的时候,会根据beanName从beanDefinitionMap中获取到beanDefinition,merge之后返回RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {// 4.这里的getBean()是去开始对beanName对应的bean初始化getBean(beanName);}}}
}

这是spring初始化前的一个判断逻辑,在第3点注释中,可以看到,是根据beanDefinition的属性进行判断,判断当前是否是单例、是否是非抽象类等
在第4处注解中,会去真正开始初始化bean,这里就有一个疑问点了,既然在第2点这里已经对beanDefinition进行了merge,为什么在getBean()的时候,不直接传beanDefinition过去,传一个beanName,岂不是还要再根据beanName获取一遍beanDefinition?
这里其实在前面mergeBeanDefinition原理
这篇笔记中有说过,在merge之后,会把beanName和merge之后的beanDefinition存到了一个集合中,在下次再次使用到的时候,就无需再次重新merge,直接从集合中获取即可
上面这个源码我们可以看到,在初始化前,会先根据beanName解析到当前class所对应的beanDefinition信息,然后在初始化的过程中,需要进行一些判断的时候,就直接根据beanDefinition的属性进行判断

自动注入模型的判断

通常说,spring有五种注入模型

/*** Constant that indicates no externally defined autowiring. Note that* BeanFactoryAware etc and annotation-driven injection will still be applied.* @see #createBean* @see #autowire* @see #autowireBeanProperties*/int AUTOWIRE_NO = 0;/*** Constant that indicates autowiring bean properties by name* (applying to all bean property setters).* @see #createBean* @see #autowire* @see #autowireBeanProperties*/int AUTOWIRE_BY_NAME = 1;/*** Constant that indicates autowiring bean properties by type* (applying to all bean property setters).* @see #createBean* @see #autowire* @see #autowireBeanProperties*/int AUTOWIRE_BY_TYPE = 2;/*** Constant that indicates autowiring the greediest constructor that* can be satisfied (involves resolving the appropriate constructor).* @see #createBean* @see #autowire*/int AUTOWIRE_CONSTRUCTOR = 3;/*** Constant that indicates determining an appropriate autowire strategy* through introspection of the bean class.* @see #createBean* @see #autowire* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,* prefer annotation-based autowiring for clearer demarcation of autowiring needs.*/@Deprecatedint AUTOWIRE_AUTODETECT = 4;

那spring源码在处理的时候,是怎么判断是哪种注入模型呢?

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBeanprotected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}
}

上面这个是属性注入源码中的部分代码,我删减了一部分,只看我们要学习的
其实spring在判断当前bean是byName,还是byType,就是根据beanDefinition中的autowireMode属性来判断的,这里所说的byType、byName和@Autowired注解的先根据类型注入,再根据name注入没有关系,不是同一个概念,@Autowired注解属于autowireMode为0的场景下的一个知识点

结论

这里说这个代码,只是为了举个例子,来说明,spring实际在对一个bean进行初始化的时候,是以beanDefinition中的属性信息为准的,所以这也是为什么spring提供了一些扩展机制,去修改beanDefinition属性信息、让程序员自己去注入beanDefinition,举个简单例子,比如说,我想将Test.class的autowireMode从默认值0,修改为1,那我们就可以通过实现ImportBeanDefinitionRegistrar接口,在其registerBeanDefinitions方法中,去修改Test类对应的beanDefinition中的autowireMode属性,为什么可以修改?因为registerBeanDefinitions这个方法有一个入参:BeanDefinitionRegistry,经常看源码的就知道,这个类提供了对beanDefinition进行增、删、改、查的方法,简单而言就是说,spring将root权限交给了程序员

所以:spring很强大,将一切都包装的很好,如果我们想自己去扩展spring,也可以,但是需要知道spring提供了哪些扩展点,以及这些扩展点的执行时机

spring的beanDefinition是什么相关推荐

  1. Spring IOC BeanDefinition解析

    Spring IOC BeanDefinition解析 IOC(Inversion of Control)即控制反转,是说创建对象的控制权进行了转移,以前创建对象的主动权和创建时机是由自己把控的,而现 ...

  2. Spring中将BeanDefinition注册到IOC容器中

    Spring中将BeanDefinition注册到IOC容器中 XML配置元信息 <bean name="-" - /> 注解: @Bean,@Component,@I ...

  3. 第二篇 再读Spring 之 BeanDefinition解析

    第二篇 再读Spring 之 BeanDefinition解析 文章目录 第二篇 再读Spring 之 BeanDefinition解析 一.颗粒度问题 二.细说Spring中不同颗粒度对象在解析中的 ...

  4. 第四篇 再读Spring 之BeanDefinition注册

    文章目录 前言 一.管理的必要性 框架设计 工程实现 二.Spring的实现 1.抽象接口BeanDefinitionRegistry 2. 具体实现DefaultListableBeanFactor ...

  5. Spring之BeanDefinition详解

    前言 Spring在初始化过程中,将xml中定义的对象解析到了BeanDefinition对象中,我们有必要了解一下BeanDefinition的内部结构,有助于我们理解Spring的初始化流程. 一 ...

  6. Spring : BeanDefinition

    1.美图 2.概述 在Java中,一切皆对象.在JDK中使用java.lang.Class来描述类这个对象. 在Spring中,存在bean这样一个概念,那Spring又是怎么抽象bean这个概念,用 ...

  7. spring源码系列一--BeanDefinition

    如果说java是由对象组成,那么spring-framework框架可以说是由BeanDefinition所构成.BeanDefinitiion其实是spring中的顶级接口,我们在阅读源码之前必须要 ...

  8. Spring官网阅读(四)BeanDefinition(上)

    前面几篇文章已经学习了官网中的1.2,1.3,1.4三小结,主要是容器,Bean的实例化及Bean之间的依赖关系等.这篇文章,我们继续官网的学习,主要是BeanDefinition的相关知识,这是Sp ...

  9. 【框架源码】Spring源码解析之BeanDefinition加载流程解析

    观看本文之前,我们先思考一个问题,Spring是如何描述Bean对象的? Spring是根据BeanDefinition来创建Bean对象,BeanDefinition就是Spring中表示Bean定 ...

  10. Spring基础面试题(一)

    Spring是什么? Spring是一个轻量级的IoC和AOP容器框架.是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求.常见的配置方式有 ...

最新文章

  1. Mac上 如何快速玩起rocksdb
  2. 时间就是金钱!Windows 上必装的 10 款高效软件
  3. Oracle RMAN 还原与恢复(一)--还原服务器参数文件
  4. hdu4280 最大流DINIC
  5. 【错误记录】VMware 虚拟机报错 ( VMWare 中的 Ubuntu 虚拟机网络设置 | 第一次网络设置 )
  6. c++ 互斥量和条件变量
  7. 【AWSL】之Linux进程和计划任务管理(ps、top、pgrep、pstree、pkill、at、crontab)
  8. 渗透测试入门16之渗透测试基本知识
  9. 手机logging什么意思_手机三轴稳定器的“三轴”是什么意思?
  10. Keras深度学习实战(1)——神经网络基础与模型训练过程详解
  11. 【注意】关于fgets函数
  12. 【facenet人脸识别】利用LFW数据集进行人脸比对测试
  13. matlab对函数时间抽样,信号与系统实验报告4 matlab时间抽样
  14. 以太坊分片Sharding FAQ
  15. WEB前端开发:轮播图的实现(H5+C3+JavaScript)(JQuery)
  16. CondaSSLError: OpenSSL appears to be unavailable on this machine
  17. linux pptpd 不能上网,CentOS7.7使用pptpd搭建服务器(配置好了,但是不能使用)
  18. 无线广播相关信号(收音机)的发射与接收
  19. 去除滚动条 去除滚动条样式 css修改滚动条样式
  20. 影响人生的十部电影(网络流传,作者不详)

热门文章

  1. 线性代数 : 矩阵消元
  2. 【概率密度函数估计】--- 最大似然估计与Parzen窗函数画法
  3. eda多功能时钟设计_Altera FPGACPLD设计 基础篇+高级篇(附随书光盘)
  4. 442.数组中重复的数据
  5. 树中两个节点的最低公共祖先节点
  6. 正确的使用URLClassLoader--ClassNotFoundException: com.mathworks.toolbox.javabuilder.internal.MWComponentI
  7. python中utf-8和gbk编码格式_Python:将utf-8格式的文件转换成gbk格式的文件|python3教程|python入门|python教程...
  8. 估计理论(7):应用BLUE的两个例子
  9. hadoop2.7.3+hbase1.2.5配合起来使用的一个小问题,备注一下
  10. 多面集的表示定理 (Representation / Resolution / Caratheodory theorem of polyhedral Sets)