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的关系

相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
1月前
|
监控 Java 应用服务中间件
Spring Boot整合Tomcat底层源码分析
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性,大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。
56 1
|
1月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
16天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
38 2
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
63 9
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
34 1
|
1月前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
34 1
|
2月前
|
缓存 JavaScript Java
Spring之FactoryBean的处理底层源码分析
本文介绍了Spring框架中FactoryBean的重要作用及其使用方法。通过一个简单的示例展示了如何通过FactoryBean返回一个User对象,并解释了在调用`getBean()`方法时,传入名称前添加`&`符号会改变返回对象类型的原因。进一步深入源码分析,详细说明了`getBean()`方法内部对FactoryBean的处理逻辑,解释了为何添加`&`符号会导致不同的行为。最后,通过具体代码片段展示了这一过程的关键步骤。
Spring之FactoryBean的处理底层源码分析
|
2月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
146 5
|
2月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
下一篇
DataWorks