【Java开发】 Spring 10 :Spring Boot 自动配置原理及实现

news/2024/5/16 16:16:50/文章来源:https://blog.csdn.net/weixin_51407397/article/details/128243758

用了这么久的 SpringBoot ,我们再来回顾一下它,本文介绍 Spring Boot 的自动配置,这是它区别于 Spring 的最大的点,本文的自动配置项目包含三个项目,建议拉取仓库里的代码进行实践:尹煜 / AutoConfigDemo · GitCode

 目录

1 介绍

2 自动配置原理

2.1 启动类注解

① @SpringBootApplication

② @SpringBootConfiguration

② @EnableAutoConfiguration

③ @ComponentScan(包扫描)

2.2 条件类注解

① 类条件

② 属性条件

③ Bean 条件

④ 资源条件

⑤ Web 应用条件

⑥ 其他条件

3 手动实现自动配置

3.1 资源配置

3.2 项目代码展示

① 主项目(autoconfigure-demo)

② 副项目(geektime-spring-boot-autoconfigure)

③ 副项目(greeting)

3.3 自动/手动配置实现

① 自动配置

② 手动配置

③ 关闭配置


1 介绍

Spring Boot 目的在于简化 Spring 繁琐的 XML 配置,本质依然还是Spring框架,使用 Spring Boot后可不再使用任何 XML 配置来启动一个服务,使得使用微服务架构时可以更加快速的建立一个应用。

Spring Boot 特点:

  • 提供了固定的配置来简化配置,即约定大于配置
  • 尽可能地自动配置 Spring 和第三方库,即能自动装配
  • 内嵌容器,创建独立的 Spring 应用
  • 让测试变的简单,内置了JUnit、Spring Boot Test等多种测试框架,方便测试
  • 提供可用于生产的特性,如度量、运行状况检查和外部化配置
  • 完全不需要生成代码,也不需要 XML 配置

2 自动配置原理

首先引用一张 Spring Boot 的自动配置原理流程图 👇

2.1 启动类注解

① @SpringBootApplication

这是 Spring Boot 启动类的注解,也是自动配置的开始 👇

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

@SpringBootApplication 用于标注在 SpringBoot 的主配置类上,也就是说项目应该运行该类的 main 方法来启动 SpringBoot 项目;其本质是一个组合注解,进入该注释的代码 👇

@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 {

查看该类的元信息,其实主要包含以下注解:

② @SpringBootConfiguration

查看一下它的源码 👇

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}
  • @Target用于定义注解的使用位置,如果没有该项,表示注解可以用于任何地方。ElementType.TYPE 表示类,接口或者枚举。
  • @Retention用于指明修饰的注解的生存周期,即会保留到哪个阶段。RUNTIME 表示运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。
  • @Documented指明修饰的注解,可以被例如 javadoc 此类的工具文档化,只负责标记,没有成员取值。
  • @Configuration表明这个一个 Spring Boot 的配置类,可以向容器中注入组件。

② @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 {};
}
  • @Inherited:用于标注一个父类的注解是否可以被子类继承,如果一个注解需要被其子类所继承,则在声明时直接使用@Inherited注解即可。如果没有写此注解,则无法被子类继承。
  • @AutoConfigurationPackage:自动导入配置包
  • @Import({AutoConfigurationImportSelector.class}):开启自动配置类的导包的选择器,即是导入哪些类,有选择性的导入。

③ @ComponentScan(包扫描)

  • 该注释用于 Configuration 类的组件扫描指令
  • 提供与 Spring XML 的 context:component-scan 元素并行的支持
  • 可以通过 basePackageClasses 或 basePackages 来定义要扫描的特定包, 如果没有定义特定的包,将从声明该注解的类的包开始扫描
  • 也可在启动类做如下配置,用于排除某些特定类包的扫描
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DataSourceTransactionManagerAutoConfiguration.class,JdbcTemplateAutoConfiguration.class})
public class DataSourceDemoApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(DataSourceDemoApplication.class, args);}
}

2.2 条件类注解

@Conditional :所有注解都基于它,是spring4引入的注解

后边的项目也将使用条件类注释来测试自动配置和手动配置~

① 类条件

  • @ConditionalOnClass:当存在一个类时,如何做
  • @ConditionalOnMissingClass:当不存在一个类时,如何做

② 属性条件

  • @ConditionalOnProperty特定的属性为什么时,做什么,如果不存在,赋给他一个默认的值

③ Bean 条件

  • @ConditionalOnBean:存在某个bean时,如何做
  • @ConditionalOnMissingBean:不存在某个bean时,如何做
  • @ConditionalOnSingleCandidate:Spring容器中是否存在且只存在一个对应的实例。只有3个属性value、type、search,跟ConditionalOnBean中的这3种属性值意义一样

④ 资源条件

  • @ConditionalOnResource:是否存在指定的资源文件。只有一个属性 resources,是个 String 数组,会从类加载器中去查询对应的资源文件是否存在

⑤ Web 应用条件

  • @ConditionalOnWebApplication:如果是web应用,如何做
  • @ConditionalOnNotWebApplication:如果不是web应用,如何做

⑥ 其他条件

  • @ConditionalOnExpression sper:表达式计算结果是怎么样的
  • @ConditionalOnJava:在特定的java版本上能做哪些事情
  • @ConditionalOnJndi Jndi:条件是如何的

3 手动实现自动配置

以下资源来自《玩转 Spring 全家桶》课程,项目源码:尹煜 / AutoConfigDemo · GitCode

3.1 资源配置

首先需要将三个项目通过 IDEA 合并在一起,主项目是 autoconfigure-demo:

首先通过 IDEA 打开主项目,然后按照下述流程逐一导入两外两个项目即可 👇

3.2 项目代码展示

项目源码:尹煜 / AutoConfigDemo · GitCode

因涉及到三个项目,且彼此呈依赖关系,因此会有点难以理解,本文希望尽可能讲得清楚一些~

① 主项目(autoconfigure-demo)

路径:geektime/spring/hello/AutoconfigureDemoApplication.java

@SpringBootApplication
public class AutoconfigureDemoApplication {public static void main(String[] args) {SpringApplication.run(AutoconfigureDemoApplication.class, args);}//	@Bean
//	public GreetingApplicationRunner greetingApplicationRunner() {
//		return new GreetingApplicationRunner("Spring!");
//	}
}

路径:src/main/resources/application.properties

greeting.enabled=true 用于搭配 @ConditionalOnProperty 的条件判断,见于第2个项目的启动类

greeting.enabled=true

路径:autoconfigure-demo\pom.xml

	<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>geektime.spring.hello</groupId><artifactId>autoconfigure-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>autoconfigure-demo</name><description>Demo project for Spring Boot</description><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- 以下是手工实现的自动配置 --><dependency><groupId>geektime.spring.hello</groupId><artifactId>geektime-spring-boot-autoconfigure</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- 以下是基于Spring Boot的自动配置 --><dependency><groupId>geektime.spring.hello</groupId><artifactId>greeting</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

② 副项目(geektime-spring-boot-autoconfigure)

路径:geektime/spring/hello/greeting/GreetingAutoConfiguration.java

@Configuration
@ConditionalOnClass(GreetingApplicationRunner.class)//当classpath中 存在GreetingApplicationRunner时 才能生效
public class GreetingAutoConfiguration {@Bean@ConditionalOnMissingBean(GreetingApplicationRunner.class)//不存在GreetingApplicationRunner这个类型的bean的时候,才能生效@ConditionalOnProperty(name = "greeting.enabled", havingValue = "true", matchIfMissing = true)//greeting.enabled这个属性为true 才能执行,如果没有配置这个值,就默认值为truepublic GreetingApplicationRunner greetingApplicationRunner() {return new GreetingApplicationRunner();}
}

路径:src/main/resources/META-INF/spring.factories

模拟 Spring Boot 的自动配置(自动配置时,Spring Boot 会扫描到类路径下的META-INF/spring.factories 配置文件,把 EnableAutoConfiguration 对应的的 Bean 值添加到容器中)

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
geektime.spring.hello.greeting.GreetingAutoConfiguration

路径:geektime-spring-boot-autoconfigure\pom.xml

该副项目也依赖 greeting 项目

	<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>geektime.spring.hello</groupId><artifactId>greeting</artifactId><version>0.0.1-SNAPSHOT</version><scope>provided</scope></dependency></dependencies>

③ 副项目(greeting)

路径:geektime/spring/hello/greeting/GreetingApplicationRunner.java

用于检验自动配置成果!

@Slf4j
public class GreetingApplicationRunner implements ApplicationRunner {private String name;public GreetingApplicationRunner(){this("OK!");}public GreetingApplicationRunner(String name) {this.name = name;log.info("Initializing GreetingApplicationRunner.{}",name);}public void run(ApplicationArguments args) throws Exception {log.info("Hello everyone! We all like Spring! ");}
}

路径:greeting\pom.xml

	<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency></dependencies>

以上,所有文件展示完毕~

3.3 自动/手动配置实现

① 自动配置

Ⅰ 注解主项目(autoconfigure-demo)中 AutoconfigureDemoApplication 启动类中的 bean

Ⅱ application.properties 中 greeting.enabled=true

启动主项目的启动类,日志输出显示自动配置成功,使用的是使用空参构造的配置--自动配置 👇

② 手动配置

Ⅰ 启动主项目(autoconfigure-demo)中 AutoconfigureDemoApplication 启动类中的 bean 👇

Ⅱ application.properties 中 greeting.enabled=true

启动主项目的启动类,日志输出显示手动配置成功,使用的是有参构造--手动配置 👇

③ 关闭配置

Ⅰ 注解主项目(autoconfigure-demo)中 AutoconfigureDemoApplication 启动类中的 bean

Ⅱ application.properties 中 greeting.enabled=false

启动主项目的启动类,日志输出显示该 bean 未被创建--关闭配置 👇


参考文章

SpringBoot自动配置原理_程序员老石的博客-CSDN博客_springboot自动配置原理

动手实现自己的自动配置_L# S@的博客-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DCDC电感下方铜箔如何处理

挖&#xff1a;电感在工作时&#xff0c;其持续变化的电流产生的电磁波会或多或少的泄露出来&#xff0c;电感下方的铜箔受电磁波影响&#xff0c;就会有涡流出现&#xff0c;这个涡流&#xff0c;①可能对线路板上的信号线有干扰&#xff0c;②铜箔内的涡流会产生热量&#xf…

容器的常用方法和线程安全(Map、List、Queue)

一、Map 1. HashTable 线程安全的Map&#xff0c;用synchronized锁 2. Collections.synchronizedMap Collections.synchronizedMap(new HashMap()) 可以把HashMap变成线程安全的&#xff0c;锁粒度比HashTable稍微小一点 3. ConcurrentHashMap ConcurrentHashMap主要提高…

某Y易盾滑块acToken、data逆向分析

内容仅供参考学习 欢迎朋友们V一起交流&#xff1a; zcxl7_7 目标 网址&#xff1a;案例地址 这个好像还没改版&#xff0c;我看官网体验那边已经进行了混淆 只研究了加密的生成&#xff0c;环境不正确可能会导致的加密结果对 (太累了&#xff0c;先缓缓吧&#xff0c;最近事比…

农业灌区量测水流量在线监测系统解决方案-灌区信息化管理系统-灌区水网智慧化

平升电子农业灌区量测水流量在线监测系统解决方案/灌区信息化管理系统/灌区水网智慧化&#xff0c;对灌区的渠道水位、流量、水雨情、土壤墒情、气象等信息进行监测&#xff0c;同时对泵站、闸门进行远程控制&#xff0c;对重点区域进行视频监控&#xff0c;实现了信息的采集、…

使用openshift 进行云平台连接

使用openshift 进行云平台连接 OpenShift CLI on Windows openshift 文档地址 OpenShift CLI on Mac 通过Homebrew方式安装 brew install openshift-cli安装完成&#xff0c;进行验证 oc version服务连接 oc login 服务地址根据提示输入用户名和密码&#xff0c;即可连接…

【日常系列】LeetCode《20·数据结构设计》

数据规模->时间复杂度 <10^4 &#x1f62e;(n^2) <10^7:o(nlogn) <10^8:o(n) 10^8<:o(logn),o(1) 内容 lc 155 【剑指 30】【top100】&#xff1a;最小栈 https://leetcode.cn/problems/min-stack/ 提示&#xff1a; -2^31 < val < 2^31 - 1 pop、top 和…

深度学习设计模式(一):编写高质量代码的基础(多例子+代码)

学习如何编写高质量代码前言面向对象面向对象编程&#xff0c;面向对象编程语言面向对象分析 &#xff0c;面向对象设计封装&#xff0c;抽象&#xff0c;继承&#xff0c;多态封装抽象继承多态面向对象比面向过程有哪些优势&#xff0c;面向过程过时了&#xff1f;什么是面向过…

MOSFET 和 IGBT 栅极驱动器电路的基本原理学习笔记(四)高侧非隔离栅极驱动

高侧非隔离栅极驱动 1.适用于P沟道的高侧驱动器 2.适用于N沟道的高侧直接驱动器 1.适用于P沟道的高侧驱动器 高侧非隔离栅极驱动可按照所驱动的器件类型或涉及的驱动电路类型来分类。相应地&#xff0c;无论是使用P沟道还是 N沟道器件&#xff0c;是实施直接驱动、电平位移驱…

代码随想录训练营第44天|完全背包、LeetCode 518. 零钱兑换 II、 377. 组合总和 Ⅳ

完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 完全背包和01背包问题唯一不同…

【Unity3D】使用GL绘制线段

1 前言 线段渲染器LineRenderer、拖尾TrailRenderer、绘制物体表面三角形网格从不同角度介绍了绘制线段的方法&#xff0c;本文再介绍一种新的绘制线段的方法&#xff1a;使用 GL 绘制线段。 Graphics Library&#xff08;简称 GL&#xff09;&#xff0c;包含一系列类似 OpenG…

MyBatisPlus入门

目录 概述 SpringBoot继承MyBatisPlus CRUD 新增 删除 修改 查询 条件构造器 全局配置 相关注解 ActiveRecord 插件 分页插件 防止全表删除插件 乐观锁插件 乐观锁插件的使用 逻辑删除 使用逻辑删除 扩展 自动填充 Sql注入器 代码生成器Generator 代码生成器MyBa…

直播预告 | SOFAChannel#31《RPC 框架设计的考和量》

SOFARPC 是蚂蚁集团开源的一款基于 Java 实现的 RPC 服务框架&#xff0c;为应用之间提供远程服务调用能力&#xff0c;具有高可伸缩性&#xff0c;高容错性&#xff0c;目前蚂蚁集团所有的业务的相互间的 RPC 调用都是采用 SOFARPC。SOFARPC 为用户提供了负载均衡&#xff0c;…

基于jsp+mysql+ssm项目bug修复管理系统-计算机毕业设计

项目介绍 本文主要是采用ssm的mvc技术、Mysql数据库、Tomcat服务器作为开发平台&#xff0c;系统采用B/S结构进行开发&#xff0c;完成一个项目修复管理系统&#xff0c;构建企业管理与员工任务计划相结合。提供了包括传统业务中最基本的用户注册、登录、查询、职位信息、部 门…

ADI Blackfin DSP处理器-BF533的开发详解21:RTC实时时钟的原理及应用(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 功能介绍 ADSP-BF53x 处理器上集成了一个实时时钟&#xff08;RTC&#xff09;模块&#xff0c;板卡上设计了一个专门用于 RTC 时钟源的晶体32.7…

78.【大二实训--《宿舍管理系统》】

大二实训--《宿舍管理系统》1.在JSP中&#xff0c;如果想要获取后端传过来的数据2.在Dao层我们用数据库的属性给实体类赋值的时候3.在一个Servlet中&#xff0c;如果想要使用多个Service4.字符串yyyy-mm-dd格式转换为Date型5.在设置实体类的时候&#xff0c;属性名开头一定要小…

TFT-LCD LVGL与硬件交互

TFT-LCD LVGL与硬件交互 屏幕能正常显示LVGL官方例程&#xff0c;说明LVGL移植成功了&#xff0c;本次实验使用屏幕通过LVGL控制开发板硬件 实现效果 用LVGL画两个按钮和一个标签&#xff0c;一个按钮控制蜂鸣器&#xff0c;另一个按钮控制继电器&#xff0c;标签显示“TFT-…

交战“低代码”,云大厂跑马圈地

者 关注 2022年末,云大厂阿里、腾讯、华为(ATH)开始了新一轮的跑马圈地。 这一次交战的战场,是低代码。 11月18日,华为AppCube全线产品全面升级,在低代码、零代码、数据看板三个方面,升级优化;11月13日,腾讯升级了云开发开发者工具“微搭”,目前已服务开发者数300万…

【图像分割】基于Kmean聚类 分水岭、oust、粒子群算法优化脂肪肝图像分割附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

手机投影到电脑显示 此设备不支持miracast,因此不能以无线投影到它

在家里使用手机的体感游戏,发现手机屏幕比较小,想要将其投影到自己的笔记本电脑上,这样看得就比较大了。然后我就打开笔记本电脑,操作如下: 如下图: 原文地址:手机投影到电脑显示 此设备不支持miracast&#xff0c;因此不能以无线投影到它 - 廖强的博客 但是结果我们就看到了…

【图像隐写】GBT+SVD数字水印嵌入与提取【含Matlab源码 1668期】

⛄一、SVD数字水印简介 理论知识参考文献&#xff1a;基于DWT和SVD的彩色图像数字水印算法研究 一种基于DWT-SVD的图像数字水印算法 ⛄二、部分源代码 clc close all clear %% Input images Iimread(‘Lena.jpg’); Iimresize(I,[512,512]); logorandsrc(8,8,[0,1]); figur…