Spring5源码 - 01 BeanDefination源码分析

简介: Spring5源码 - 01 BeanDefination源码分析

20200914143739548.png

引入

Spring 是如何生成一个Bean的?

我们先看个例子


2020091108493851.png


我们有个Configuration类AppConfig ,通过ComponentScan定义了扫描com.artisan目录下所有表了标注了注解的Bean

package com.artisan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.artisan")
public class AppConfig {
}

同时com.artisan目录下还有A.class 和 B.class , 其中B类上标注了@Component注解,A上仅仅一个普通的Java类

package com.artisan.test;
import org.springframework.stereotype.Component;
@Component
public class B { 
}
package com.artisan.test;
public class A {
}

我们启动下Spring容器,然后尝试去重bean容器中获取A和B的单例对象,看看会发生什么?

package com.artisan.test;
import com.artisan.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BeanLoadTest {
  public static void main(String[] args) {
    // spring容器
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
    System.out.println(ac.getBean(B.class));
    System.out.println(ac.getBean(A.class));
  }
}


结果显而易见, 被标注了@Component注解的B类,成功的从bean容器中获取到了,而A类是无法从bean容器中获取到的 ( No qualifying bean of type ‘com.artisan.test.A’ available)。

com.artisan.test.B@28864e92
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.artisan.test.A' available
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
  at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1177)
  at com.artisan.test.BeanLoadTest.main(BeanLoadTest.java:12)


这是为什么呢?Spring的源码是如何实现的呢? 接下来的文章,我们逐层揭开Sping Bean的神秘面纱 …


Bean实例化的原理


我们知道普通的Java类的实例化的过程,被JVM编译成字节码文件以后,通过new 关键字实例化。


Spring bean的实例化区别于普通Java类的实例化过程,是一个相对复杂的过程。


原理如下


1. 扫描到可以受到Spring管理的Bean,将其转化成BeanDefinition


2. BeanDefinition是个接口,其中有很多属性可以设置,比如 scope 、lazyInit、dependson 、autoType 、关联的是哪个类setBeanClass 等等


3. 将BeanDefinition放入到一个Map中


4. 遍历Map ,取出BeanDefinition,根据你上一步设置的各种属性,去做不同的操作,比如autoType 、是否懒加载等等等等,实例化Bean


5. 实例化完成以后,将实例化好的Bean放到map中 (就是spring容器),即Spring的单例池 singletonObjectsMap。


这里只会创建单例模式的Bean,prototype等类型的bean不会添加到单例池中,因为prototype每次都会new一个,没有必要去缓存。


当然了,Spring的实现是很复杂的,我们这里先对其大致的过程和原理有个初步的了解,方便后续源码的展开


20200911092320666.png

singleton vs prototype


spring容器在启动的时候就已经将singleton的bean 缓存到 单例池中,而 prototype类型的bean ,在spring容器启动的时候并不会被实例化,仅在调用的时候生成,且每次都一个新的对象 。

看个演示20200911095006795.png


加个断点,

可以发现 还没执行到ac.getBean(B.class),仅在容器启动阶段就已经实例化完成了singleton作用域的bean。

20200911095209116.png


接下来我们看下prototype类型的bean


20200911095236463.png


可以看到 在spring容器启动的时候,并没有实例化prototype类型的bean 。


2020091109540837.png

20200911095530349.png

Singleton VS Prototype 小结


我们看到了 Singleton VS Prototype的区别

  1. 创建时机不同: singleton的bean是在容器初始化的时候创建的,而原型bean是在调用的时候创建的
  1. 作用域不同: 单例singleton的bean 在容器中仅会创建一次,并且只有一个,而原型Prototype类型的bean每次调用都会初始化一个新的对象。


下文


下文我们探讨对象和bean的关系

相关文章
|
7天前
|
Java 应用服务中间件 Nacos
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
21 0
|
10天前
|
监控 数据可视化 安全
一套成熟的Spring Cloud智慧工地平台源码,自主版权,开箱即用
这是一套基于Spring Cloud的智慧工地管理平台源码,具备自主版权,易于使用。平台运用现代技术如物联网、大数据等改进工地管理,服务包括建设各方,提供人员、车辆、视频监控等七大维度的管理。特色在于可视化管理、智能报警、移动办公和分布计算存储。功能涵盖劳务实名制管理、智能考勤、视频监控AI识别、危大工程监控、环境监测、材料管理和进度管理等,实现工地安全、高效的智慧化管理。
|
29天前
|
消息中间件 NoSQL Java
Spring Cloud项目实战Spring Cloud视频教程 含源码
Spring Cloud项目实战Spring Cloud视频教程 含源码
30 1
|
1月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
2月前
|
监控 数据可视化 关系型数据库
微服务架构+Java+Spring Cloud +UniApp +MySql智慧工地系统源码
项目管理:项目名称、施工单位名称、项目地址、项目地址、总造价、总面积、施工准可证、开工日期、计划竣工日期、项目状态等。
308 6
|
2月前
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
35 1
|
1月前
|
Java 测试技术 数据库连接
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
|
1天前
|
设计模式 安全 Java
【初学者慎入】Spring源码中的16种设计模式实现
以上是威哥给大家整理了16种常见的设计模式在 Spring 源码中的运用,学习 Spring 源码成为了 Java 程序员的标配,你还知道Spring 中哪些源码中运用了设计模式,欢迎留言与威哥交流。
21 0
|
5天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
11天前
|
Java Maven Nacos
Spring Cloud Eureka 服务注册和服务发现超详细(附加--源码实现案例--及实现逻辑图)
Spring Cloud Eureka 服务注册和服务发现超详细(附加--源码实现案例--及实现逻辑图)
23 0