一文足够,SpringBoot自动装配底层源码

这篇具有很好参考价值的文章主要介绍了一文足够,SpringBoot自动装配底层源码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

自动装配原理

开始深入源码

总结自动装配原理


首先明白一个概念,什么是自动装配?

我们在项目中建一个yaml或者properties文件,里面配置一些参数,如redis,在pom中引入启动器,之后就能用redis,自动把这些集成到spring中,这就是自动装配。

先来提前剧透:

加载spring.factories文件

标记好启动类

解析启动类的注解

加载EnableAutoConfiguration

 

自动装配原理

开始深入源码

启动类中

创建SpringApplication,调用run方法,这里面是核心逻辑

为什么把启动类作为参数传进去? 因为后期需要获取这个启动类上的注解,进入run方法

一文足够,SpringBoot自动装配底层源码

primarySource就是启动类

一文足够,SpringBoot自动装配底层源码

这里new SpringApplication,注意看源码时不要忽略new,为什么?因为new,会调用构造方法,而很多初始化操作会在构造方法中定义

 一文足够,SpringBoot自动装配底层源码

进入

注意下面的两行代码

这里涉及到spring.factories这个文件是如何读取与加载的,包括用户自己怎么定义spring.factories

一文足够,SpringBoot自动装配底层源码

我们先进入setInitializers这行代码中

一文足够,SpringBoot自动装配底层源码

先获取工厂的名字,之后加载工厂

从缓存中获取,如果缓存中没有会从classpath中查找我们需要的配置文件,配置属性

一文足够,SpringBoot自动装配底层源码

指定了路径

一文足够,SpringBoot自动装配底层源码

方法的后半部分,就是把获取的属性,变成properties的格式

一文足够,SpringBoot自动装配底层源码

最后一步就是把查询到的数据,放到缓存中,方便下次数据的读取。

不需要重新查询,不需要重新加载配置文件等,加快速度

 一文足够,SpringBoot自动装配底层源码

 之后返回结果到刚才的方法,把获取的类名称,实例化

一文足够,SpringBoot自动装配底层源码

 返回到

一文足够,SpringBoot自动装配底层源码

 setListeners这行代码的处理逻辑和上面一样

public ConfigurableApplicationContext run(String... args) {
//时间的处理
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
//上下文  就是一个全局变量,保存全局数据,供其他人使用
		ConfigurableApplicationContext context = null;
//异常汇报器
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
//获取监听器
		SpringApplicationRunListeners listeners = getRunListeners(args);
//  spring,springBoot对于观察者模式,使用是非常多的
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
//封装环境变量
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
//上面都是一些赋值准备工作
//下面这行才是重要
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			refreshContext(context);
		......
	}

spring,springBoot对于观察者模式使用是非常多的,如Listener,event

其中Environment接口有个实现类,standardEnvironment

一文足够,SpringBoot自动装配底层源码

这个standerEnvironment类会加载系统的环境和属性值,比如java版本,java classpath,编码格式等

一文足够,SpringBoot自动装配底层源码

进入到prepareContext方法中 

一文足够,SpringBoot自动装配底层源码

前面讲过这个primarySource就是启动类,这里会去找primarySource,也就是找启动类

一文足够,SpringBoot自动装配底层源码

那么为什么要找启动类?是为了解析启动类上的注解,这是核心

之后load加载,进入方法

一文足够,SpringBoot自动装配底层源码

提示:Spring通过反射创建对象前,必须要有BeanDefinition(bean定义),BeanDefinition中保存的是属性值

 创建BeanDefinition,设置一些属性值,之后调用loader.load方法

一文足够,SpringBoot自动装配底层源码

 判断source类型,我们的是类启动器,所以是Class,满足第一个if判断

一文足够,SpringBoot自动装配底层源码

 一文足够,SpringBoot自动装配底层源码

通过注解读取器来读取注解信息 ,注意这里只是加载好注解信息,做好标识,没有解析。之后返回到前面的prepareContext中,此时已经加载完了注解信息

一文足够,SpringBoot自动装配底层源码

返回到prepareContext中,已加载注解信息,待解析。

一文足够,SpringBoot自动装配底层源码

refresh在spring中是个很重要的方法,当带有refresh前缀时,表示它要调用refresh方法了,同时这个方法也是重要的。

如果点击进入refreshContext方法,其底层就是调用的refresh,如果不调用,是没法创建bean的

在详细分析refreshContext方法前,我们先来了解一些知识点

spring为什么这么火?

一是因为全生态,有所有的技术组件,我想用的技术,几乎都有相应的框架。

二是扩展性,代码不能是死的,可以根据你的业务需求来动态扩展

spring中有两个重要的扩展接口:postProcessor(后置处理器,个人认为增强器),是为了完成扩展功能的,做对应的扩展实现。有两个代表:BeanFactoryPostProcessor和BeanPostProcessor

一文足够,SpringBoot自动装配底层源码

 SpringBoot自动装配的实质就是从spring.factories文件中获取到相应的Bean对象,并由Spring容器来帮我们进行管理

spring.factories文件中存的是类的完全限定名,我们可以通过反射来实例化出具体的Bean对象,而这些Bean对象会放到BeanFactory中。如果我想扩展,就用BeanFactoryPostProcessor

注意逻辑

无论是配置,还是注解,都是为了创建BeanDefinition,之后通过反射实例化获取Bean对象

一文足够,SpringBoot自动装配底层源码

refreshContext方法最后还是调用的refresh方法

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 准备刷新,初始化容器等
			prepareRefresh();

			// 获取最新的BeanFactory工厂,用来生产bean
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 设置属性
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// 很重要  增强器或者后置处理器  这里实现的自动装配
				invokeBeanFactoryPostProcessors(beanFactory);

				......
	}

进入invokeBeanFactoryPostProcessors(beanFactory)方法

里面有

一文足够,SpringBoot自动装配底层源码

这个BeanDefinitionRegistryPostProcessor就是刚才BeanFactoryPostProcessor的子接口

这个方法就是去Bean工厂中,找有没有归属于这个BeanDefinitionRegistryPostProcessor的类对象,最后返回

一文足够,SpringBoot自动装配底层源码

 这里会有个转换,在AnnotationConfigUtils中 定义了这个字符串

一文足够,SpringBoot自动装配底层源码

然后根据字符串匹配对应的类 

比如上面的字符串就匹配后就会BeanDefinition中放入ConfigirationClassPostProcessor,生成BeanDefinition

一文足够,SpringBoot自动装配底层源码

实际解析的类是ConfigirationClassPostProcessor,本质是BeanFactoryPostProcessor,不是配置类,是配置的增强类

继续往下

一文足够,SpringBoot自动装配底层源码

这个方法内部会进行一些调用

通过BeanDefinitionRegistry的BeanDefinitionName方法获取到集合

之后循环判断,根据规则判断集合中的每一个BeanName是不是配置增强类,

经过判断,最后只获得启动类。

(如下图Debug,我们的启动类就叫springbootDataApplication)

一文足够,SpringBoot自动装配底层源码

之后就开始解析

解析每一个被@Configuration修饰的类,我们的启动类也被修饰了

用解析器,解析启动类

里面通过递归来逐层解析@PropertySource,@ComponentScan,@Import,@Bean等注解

解析完成后到下面这个方法,这个方法比较重要

一文足够,SpringBoot自动装配底层源码

各种方法调用 

一文足够,SpringBoot自动装配底层源码

 一文足够,SpringBoot自动装配底层源码

 一文足够,SpringBoot自动装配底层源码  

一文足够,SpringBoot自动装配底层源码

一文足够,SpringBoot自动装配底层源码

进入getCandidateConfigurations方法中 

注意这里的SpringFactoryLoader,就是前面setInitializers那部分,读取spring.factory,然后

前面已经读取了spring.factory放到缓存中了。

一文足够,SpringBoot自动装配底层源码

根据类型把EnableAutoConfiguration取出来

一文足够,SpringBoot自动装配底层源码

 注意取出来多少个EnableAutoConfiguration?一百多个

但是不会全部加载,pom里依赖什么,我加入什么

一文足够,SpringBoot自动装配底层源码

所以在getExclusions中判断去除哪些东西,remove它们。

最后configurations里就是我们需要用到的配置

一文足够,SpringBoot自动装配底层源码

 之后获取实例

总结自动装配原理


1、当启动springboot应用程序的时候,会先创建SpringApplication的对象,在对象的构造方法中会进行某些参数的初始化工作,最主要的是判断当前应用程序的类型以及初始化器和监听器,在这个过程中会加载整个应用程序中的spring.factories文件,将文件的内容放到缓存对象中,方便后续获取。


2、SpringApplication对象创建完成之后,开始执行run方法,来完成整个启动,启动过程中最主要的有两个方法,第一个叫做prepareContext,第二个叫做refreshContext,在这两个关键步骤中完整了自动装配的核心功能,前面的处理逻辑包含了上下文对象的创建,banner的打印,异常报告期的准备等各个准备工作,方便后续来进行调用。


3、在prepareContext方法中主要完成的是对上下文对象的初始化操作,包括了属性值的设置,比如环境对象,在整个过程中有一个非常重要的方法,叫做load,load主要完成一件事,将当前启动类做为一个beanDefinition注册到registry中,方便后续在进行BeanFactoryPostProcessor调用执行的时候,找到对应的主类,来完成@SpringBootApplicaiton,@EnableAutoConfiguration等注解的解析工作。


4、在refreshContext方法中会进行整个容器刷新过程,会调用中spring中的refresh方法,refresh中有13个非常关键的方法,来完成整个spring应用程序的启动,在自动装配过程中,会调用invokeBeanFactorvPostProcessor方法,在此方法中主要是对ConfigurationClassPostProcessor类的处理,这次是BeanFactoryPostProcessor的子类也是BeanDefinitionRegistryPostProcessor的子类,在调用的时候会先调用BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法,然后调用postProcessBeanFactory方法,在执行postProcesskeanDefinitionRegistry的时候回解析处理各种注解,包含@PropertySource,@ComponentScan,@ComponentScans,@Bean,@lmport等注解,最主要的是@Import注解的解析


5、在解析@lmport注解的时候,会有一个getlmports的方法,从主类开始递归解析注解,把所有包含@lmport的注解都解析到,然后在processlmport方法中对lmport的类进行分类,此处主要识别的时候AutoConfigurationlmportSelect归属于ImportSelect的子类,在后续过程中会调用deferredlmportSelectorHandler中的process方法,来完整EnableAutoConfiguration的加载文章来源地址https://www.toymoban.com/news/detail-412311.html

到了这里,关于一文足够,SpringBoot自动装配底层源码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot:自动配置源码底层原理分析

    声明:原文作者:yuan_404 配置文件到底能写什么?怎么写? SpringBoot 官方文档中有大量的配置,我们无法全部记住 ,下面我们就梳理一下最核心的几个部分进行讲解。 以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理; @Configuration(proxyBeanMethods = false) 表示

    2023年04月09日
    浏览(27)
  • 一文读懂Spring IOC从演变到自动装配的全攻略

    目录 一、前言 1.1.Spring简介 1.2.使用Spring的优点 1.3.Spring组成 二、Spring之IOC详解 2.1.IOC理论推导 2.1.1.IOC分析实现 2.1.2.IOC本质 2.2.Maven项目导入Jar包 2.3.依赖注入 2.3.1.Set注入(重点) 2.3.2.构造注入 无参构造创建对象 有参构造创建对象 2.4.自动装配 byName(按名称自动装配) byType 

    2024年02月09日
    浏览(27)
  • SpringBoot自动装配原理

            自动装配简单来说就是自动去把第三方的组件bean加载到springIOC容器当中,不需要开发人员再去写bean相关的配置,springboot应用里面只需要把@SpringbootApplication注解加在启动类上边,就可完成自动配置的功能,而@SpringbootApplication是一个复合注解,真正完成自动配置功

    2024年01月22日
    浏览(36)
  • Springboot的自动装配解读

    目录   1.Springboot的自动装配 1.1 组件装配 1.1.1 组件 1.2 Spring Framework 的模块装配 1.2.1 @Import注解 1.2.2 BeanDefinition  1.3 Spring Framework 的条件装配 1.3.1 @Profile 1.3.2 @Conditional  1.3.3 MetaData元数据接口(补充) AnnotatedTypeMetadata AnnotationMetadata MethodMetadata  1.4 SPI机制 1.5 Springboot 的装配机

    2024年02月11日
    浏览(31)
  • springBoot 自动装配

    1.前言 自动装配则是 SpringBoot 的核心,自动装配是如何实现的呢?为什么我们只要引入一个 starter 组件依赖就能实现自动装配呢,接下来就让我们一起来探讨下 SpringBoot 的自动装配机制 2.自动装配原理 提到自动装配,那么你首先得知道JDK的SPI(serviceproviderinterface)机制,因为

    2024年02月09日
    浏览(30)
  • springBoot自动装配机制

    自动配置原理 @SpringBootApplication 是一个组合注解,由 @ComponentScan、@EnableAutoConfiguration 和 @SpringBootConfiguration 组成 @SpringBootConfiguration 与普通 @Configuration 相比,唯一区别是前者要求整个 app 中只出现一次 @ComponentScan excludeFilters - 用来在组件扫描时进行排除,也会排除自动配置类

    2024年02月08日
    浏览(37)
  • springboot自动装配大概原理

    自动装配 : pom.xml spring-boot-dependence:核心都依赖在父类工程中! 我们在写入或者引入springboot依赖的时候,不需要指定版,因为有这些仓库的版本 启动器:------spring boot的启动场景 比如spring-boot-starter-web,他就会帮我们导入web环境苏需要的依赖。 springboot会将所有的功能场景

    2023年04月25日
    浏览(26)
  • Spring框架之一文读懂Spring IOC从演变到自动装配的全攻略

    目录 一、前言 1.1.Spring简介 1.2.使用Spring的优点 1.3.Spring组成 二、Spring之IOC详解 2.1.IOC理论推导 2.1.1.IOC分析实现 2.1.2.IOC本质 2.2.Maven项目导入Jar包 2.3.依赖注入 2.3.1.Set注入(重点) 2.3.2.构造注入 无参构造创建对象 有参构造创建对象 2.4.自动装配 byName(按名称自动装配) byType 

    2024年02月11日
    浏览(25)
  • SpringBoot自动装配原理及分析

    在使用SpringBoot的时候,会自动将Bean装配到IOC容器中。例如我们在使用Redis数据库的时候,会引入依赖spring-boot-starter-data-redis。在引入这个依赖后,服务初始化的时候,会将操作Redis需要的组件注入到Ioc容器中进行后续使用。 自动装配的大致过程如下: 获取到组件(spring-boo

    2024年01月21日
    浏览(32)
  • springboot启动流程 (3) 自动装配

    在SpringBoot中,EnableAutoConfiguration注解用于开启自动装配功能。 本文将详细分析该注解的工作流程。 启用SpringBoot自动装配功能,尝试猜测和配置可能需要的组件Bean。 自动装配类通常是根据类路径和定义的Bean来应用的。例如,如果类路径上有tomcat-embedded.jar,那么可能需要一个

    2024年02月09日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包