Spring Boot自动装配原理

news2024/11/13 14:59:33

Spring Boot自动装配原理

  • 1.Spring Boot 入口
  • 2.@SpringBootApplication
    • @SpringBootConfiguration
    • @ComponentScan
    • @EnableAutoConfiguration
      • 判断自动装配开关是否打开
      • 获取EnableAutoConfiguration注解中的 exclude 和 excludeName
      • 获取需要自动装配的所有配置类
      • 最后
  • 3.总结

1.Spring Boot 入口

Spring Boot 的入口是如下的main方法:

@SpringBootApplication
public class TestBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestBootApplication.class, args);
    }
}

其中:

@SpringBootApplication标注这个应用是一个SpringBoot应用,是一个完全必要的注解

SpringApplication.run,用于将SpringBoot应用启动!


2.@SpringBootApplication

这个注解是SpringBoot 的核心注解 SpringBootApplication

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};
	
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;
}

可以看到SpringBootApplication注解的源码还包含了其他三个重要注解:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

大概可以把@SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。根据 SpringBoot 官网,这三个注解的作用分别是:

  • @Configuration:允许在上下文中注册额外的 bean 或导入其他配置类
  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
  • @ComponentScan: 扫描被@Component (@Service,@Controller)注解的bean,注解默认会扫描启动类所在的包下所有的类

@SpringBootConfiguration

源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}
  • @SpringBootConfiguration 是继承自Spring的 @Configuration 注解
  • @SpringBootConfiguration 作用相当于 @Configuration

总结,@Configuration相当于一个spring的xml文件,配合@Bean注解,可以在里面配置需要Spring容器管理的bean

@ComponentScan

@ComponentScan通常与@Configuration一起配合使用,相当于xml里面的<context:component-scan>,用来告诉Spring需要扫描哪些包或类。如果不设值的话默认扫描@ComponentScan注解所在类的同级类和同级目录下的所有类,所以对于一个Spring Boot项目,一般会把入口类放在顶层目录中,这样就能够保证源码目录下的所有类都能够被扫描到。

@EnableAutoConfiguration

@EnableAutoConfiguration 是实现自动装配的重要注解,我们以这个注解入手。

源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
	
	Class<?>[] exclude() default {};

	String[] excludeName() default {};

}

其中,@AutoConfigurationPackage的作用是自动配置包

@EnableAutoConfiguration 注解的核心是@Import(AutoConfigurationImportSelector.class)里面导入的AutoConfigurationImportSelector.class

我们现在重点分析下AutoConfigurationImportSelector 类到底做了什么?🙌

AutoConfigurationImportSelector类的继承体系如下:

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

}

public interface DeferredImportSelector extends ImportSelector {

}

public interface ImportSelector {
    String[] selectImports(AnnotationMetadata var1);
}

可以看出,AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    // 判断自动装配开关是否打开
	if (!isEnabled(annotationMetadata)) {
		return NO_IMPORTS;
	}
	// 获取所有需要装配的bean
	AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
	return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

这里我们需要重点关注一下getAutoConfigurationEntry()方法,这个方法主要负责加载自动配置类的。

现在我们结合getAutoConfigurationEntry()的源码来详细分析一下:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return EMPTY_ENTRY;
	}
	AnnotationAttributes attributes = getAttributes(annotationMetadata);
	List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
	configurations = removeDuplicates(configurations);
	Set<String> exclusions = getExclusions(annotationMetadata, attributes);
	checkExcludedClasses(configurations, exclusions);
	configurations.removeAll(exclusions);
	configurations = getConfigurationClassFilter().filter(configurations);
	fireAutoConfigurationImportEvents(configurations, exclusions);
	return new AutoConfigurationEntry(configurations, exclusions);
}

注意了!重头戏来了!

判断自动装配开关是否打开

在这里插入图片描述

默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置:

在这里插入图片描述

获取EnableAutoConfiguration注解中的 exclude 和 excludeName

在这里插入图片描述

获取需要自动装配的所有配置类

获取需要自动装配的所有配置类,读取META-INF/spring.factories

先看一下META-INF/spring.factories文件所在的位置:

在这里插入图片描述

在这里插入图片描述

从下图可以看到这个文件的配置内容都被我们读取到了。XXXAutoConfiguration的作用就是按需加载组件。

在这里插入图片描述

不光是这个依赖下的META-INF/spring.factories被读取到,所有 Spring Boot Starter 下的META-INF/spring.factories都会被读取到。

所以,你可以清楚滴看到, druid 数据库连接池的 Spring Boot Starter 就创建了META-INF/spring.factories文件。

如果,我们自己要创建一个 Spring Boot Starter,这一步是必不可少的。

在这里插入图片描述

最后

到这里可能面试官会问你:“spring.factories中这么多配置,每次启动都要全部加载么?”。

很明显,这是不现实的。我们 debug 到后面你会发现,configurations 的值变小了。

在这里插入图片描述

因为,这一步又经历了一遍筛选,@ConditionalOnXXX 中的所有条件都满足,该类才会生效。

@Configuration
// 检查相关的类:RabbitTemplate 和 Channel是否存在
// 存在才会加载
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
}

3.总结

  1. SpringBoot在启动的时候,从类路径下/META-lNF/spring.factories获取指定的值
  2. 将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置
  3. 以前我们需要自动配置的东西,现在SpringBoot帮我们做了
  4. 整合javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.2.0.RELEASE.jar这个包下
  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
  6. 容器中也会存在非常多的xxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场录需要的所有组件:并自动配置,@Configuration,JavaConfig!
  7. 有了自动配置类,免去了我们手动编写配置文件的工作!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/80108.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Github访问量过百万!阿里内部至尊级分布式事务手册,实至名归

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说&#xff0c;就是一次大的操作由不同的小操作组成&#xff0c;这些小的操作分布在不同的服务器上&#xff0c;且属于不同的应用&#xff0c;分布式…

[附源码]JAVA毕业设计养生药膳推荐系统(系统+LW)

[附源码]JAVA毕业设计养生药膳推荐系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

[LeetCode周赛复盘] 第 323 场周赛20221211

[LeetCode周赛复盘] 第 323 场周赛20221211 一、本周周赛总结二、 [Easy] 6257. 删除每行中的最大值1. 题目描述2. 思路分析3. 代码实现三、[Medium] 6258. 数组中最长的方波1. 题目描述2. 思路分析3. 代码实现四、[Medium] 6259. 设计内存分配器1. 题目描述2. 思路分析3. 代码…

web前端期末大作业【足球网页】学生网页设计作业源码

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

基于C++实现(控制台)单位职工管理系统(数据结构)【100010017】

1需求分析 1.1 问题描述 对单位的职工进行管理&#xff0c; 包括插入、 删除、 查找、 排序等功能。 1.2 问题要求 职工对象数不必很多&#xff0c; 便于一次读入内存&#xff0c; 所有操作不经过内外存交换。 &#xff08;1&#xff09; 由键盘输 入职工对象&#xff0c;…

1564_AURIX_TC275_电压监控寄存器整理

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 1. 如果HSM保护开启了&#xff0c;那么访问修改其他的bit就会导致一个总线错误。 2. SMU中可以配置电压监控的相关alarm是否配置 生效。 这个寄存器是几个欠压阈值的配置&#xff0c;在这…

在Ubuntu中为ROG笔记本安装驱动asusctl

我是在Kubuntu22.04上安装的&#xff0c;系统自带“省电”、“平衡”、“性能”三个电源选项&#xff0c;显卡模式切换是拿nvidia驱动切换的&#xff0c;所以目前装的这个驱动我只用到了灯光调节功能。 文章目录介绍安装安装asusctl卸载显卡模式切换驱动supergfxctl使用方法启用…

LwIP——无操作系统启动流程

目录 启动流程 虚拟网卡控制块 发送流程 接收流程 总结 启动流程 通过阅读正点原子的无操作系统移植工程的源码&#xff0c;可以总结出LwIP的无操作系统的启动流程。 前面一些都是基于其他的外设的初始化&#xff0c;我们只关心这里lwip_comm_init()&#xff0c;这个函数的…

eve-ng ubuntu 20.04 设置iptables

eve-ng ubuntu 20.04 设置iptables一、设置方法1、建立iptables规则开机加载脚本2、建立iptables规则关机/重启保存脚本3、添加可执行权限4、保存当前iptables规则到配置文件二、命令解释一、设置方法 1、建立iptables规则开机加载脚本 sudo vi /etc/network/if-pre-up.d/ipt…

(十一)Vue之条件渲染

文章目录v-if与v-else-if、v-else一起使用v-show关于 <template>标签Vue学习目录 上一篇&#xff1a;&#xff08;十&#xff09;Vue之绑定样式 v-if v-if&#xff0c;默认为true&#xff0c;如果为false&#xff0c;底层实现是直接把这个节点删除 适用于&#xff1a;…

MLE,MAP,经验风险最小化,结构风险最小化,邻域风险最小化

文章目录Maximun likelihood extimationMaximum A Posterior EstimationVicinal Risk Minimization, VRMMaximun likelihood extimation 最大似然估计:样本->参数,完全相信观测到的数据,最优可能产生这些看到的数据的模型就是最理想的模型. 频率学派认为,参数是一个常数,不…

fpga实操训练(基础)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 之前我们虽然说过怎么编写verilog代码&#xff0c;怎么用iverilog软件和gtkwave软件进行仿真验证&#xff0c;但是一直没有说明如何在真实的板子上…

web前端期末大作业——基于HTML+CSS+JavaScript仿蘑菇街时尚服装购物商城

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

28个你应该知道的JavaScript技巧

今天我将分享一些Javascript中的常用技巧&#xff0c;以帮助您解决问题。设置过程中的常见问题更快更容易。 01、Javascript 反向字符串 下面是代码&#xff1a; /*niemvuilaptrinh.com*/const stringReverse str > str.split("").reverse().join("")…

搜索引擎项目测试报告

目录单元测试构建索引模块文档信息对象Document的构建的单元测试**针对每一篇文档进行分析、处理、分词**针对文档内容提取关键字的测试&#xff08;正则表达式&#xff09;测试去掉script测试去掉标签完整测试Document类中的parseContent方法关于ansj分词器的测试关于构建倒排…

CleanMyMac4.12.2最新免费的macOS电脑清理工具

相信不少的小伙伴都在用苹果电脑&#xff0c;不论是 iMac&#xff0c;还是 MacBook&#xff0c;用着用着电脑就变慢了。这通病与苹果电脑的性能无关&#xff0c;主要是硬盘空间不足的问题&#xff01;当然你可以在购买电脑的时候就把硬盘升级&#xff0c;但主要的问题是 – 没有…

python代码圣诞树你还没有嘛?所有画法都在这篇文章里拉~

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~ 今天&#xff0c;我就来给大家分享一下python制作的几种圣诞树吧~ 一&#xff1a;唯美圣诞 代码展示 导入模块 完整源码点击领取即可 import turtle as t from turtle import * import random as r import time n 100.0spee…

【JavaWeb】Tomcat的入门使用

1Tomcat的相关概念: Tomcat是Apache软件基金会一个核心项目&#xff0c;是一个开源免费的轻量级Web服务器&#xff0c;支持Servlet/JSP少量JavaEE规范。 概念中提到了JavaEE规范&#xff0c;那什么又是JavaEE规范呢? JavaEE: Java Enterprise Edition,Java企业版。指Java企业…

5年Java开发干到月薪38k?当初实习期2.5k的苦我也吃过...

每一个能在所属行业中成为佼佼者的人&#xff0c;一定都会有他自己的独到的见解以及成长方法......这个观点我非常认同&#xff0c;我不自诩自己是个大佬&#xff0c;但现在也算是做出了头&#xff0c;我从刚毕业做 Java 实习生月薪 2.5k&#xff0c;到现在干了 5 年 Java 开发…

仿雷速体育app踢足球tab

MyTabLayout MyTabLayout用法参照BaseLibrary的Demo GitHub仓库地址 效果图 引入 gradle allprojects {repositories {maven { url https://jitpack.io }} }implementation com.github.DL-ZhangTeng:BaseLibrary:2.3.0属性 MyTabLayout属性名描述&#xff1a;可参考原生控…