(2)SpringBoot学习——芋道源码

Spring Boot 的自动配置

1.概述

EmbeddedWebServerFactoryCustomizerAutoConfiguration 类

@Configuration // <1.1>
@ConditionalOnWebApplication // <2.1>
@EnableConfigurationProperties(ServerProperties.class) // <3.1>
public class  EmbeddedWebServerFactoryCustomizerAutoConfiguration {

	/**
	 * Nested configuration if Tomcat is being used.
	 */
	@Configuration // <1.2>
	@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })
	public static class TomcatWebServerFactoryCustomizerConfiguration {

		@Bean
		public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(
				Environment environment, ServerProperties serverProperties) {
			// <3.2>
			return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
		}

	}

	/**
	 * Nested configuration if Jetty is being used.
	 */
	@Configuration // <1.3>
	@ConditionalOnClass({ Server.class, Loader.class, WebAppContext.class })
	public static class JettyWebServerFactoryCustomizerConfiguration {

		@Bean
		public JettyWebServerFactoryCustomizer jettyWebServerFactoryCustomizer(
				Environment environment, ServerProperties serverProperties) {
			 // <3.3>
			return new JettyWebServerFactoryCustomizer(environment, serverProperties);
		}

	}

	/**
	 * Nested configuration if Undertow is being used.
	 */
	// ... 省略 UndertowWebServerFactoryCustomizerConfiguration 代码

	/**
	 * Nested configuration if Netty is being used.
	 */
	// ... 省略 NettyWebServerFactoryCustomizerConfiguration 代码

}
  • ① 配置类
  • ② 条件注解
  • ③ 配置属性

① 配置类
<1.1> 处,在类上添加了 @Configuration 注解,声明这是一个配置类。因为它的目的是自动配置,所以类名以 AutoConfiguration 作为后缀。

<1.2>、<1.3> 处,分别是用于初始化 Tomcat、Jetty 相关 Bean 的配置类。

  • TomcatWebServerFactoryCustomizerConfiguration 配置类,负责创建 TomcatWebServerFactoryCustomizer Bean,从而初始化内嵌的 Tomcat 并进行启动。
  • JettyWebServerFactoryCustomizer 配置类,负责创建
    JettyWebServerFactoryCustomizer Bean,从而初始化内嵌的 Jetty 并进行启动。

结论一:通过 @Configuration 注解的配置类,可以解决“创建哪些 Bean”的问题。

② 条件注解
<2> 处,在类上添加了 @ConditionalOnWebApplication 条件注解,表示当前配置类需要在当前项目是 Web 项目的条件下,才能生效。在 Spring Boot 项目中,会将项目类型分成 Web 项目(使用 SpringMVC 或者 WebFlux)和非 Web 项目。这样我们就很容易理解,为什么 EmbeddedWebServerFactoryCustomizerAutoConfiguration 配置类会要求在项目类型是 Web 项目,只有 Web 项目才有必要创建内嵌的 Web 服务器呀。
<2.1>、<2.2> 处,在类上添加了 @ConditionalOnClass 条件注解,表示当前配置类需要在当前项目有指定类的条件下,才能生效。

  • TomcatWebServerFactoryCustomizerConfiguration 配置类,需要有tomcat-embed-core 依赖提供的 Tomcat、UpgradeProtocol 依赖类,才能创建内嵌的 Tomcat服务器。
  • JettyWebServerFactoryCustomizer 配置类,需要有 jetty-server 依赖提供的 Server、Loader、WebAppContext 类,才能创建内嵌的 Jetty 服务器。
    结论二:通过条件注解,可以解决“满足什么样的条件?”的问题。

③ 配置属性
< 3.1> 处,使用 @EnableConfigurationProperties 注解,让 ServerProperties 配置属性类生效。在 Spring Boot 定义了 @ConfigurationProperties 注解,用于声明配置属性类,将指定前缀的配置项批量注入到该类中。例如 ServerProperties 代码如下:

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties
		implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {

	/**
	 * Server HTTP port.
	 */
	private Integer port;

	/**
	 * Context path of the application.
	 */
	private String contextPath;
	
	// ... 省略其它属性
	
}
  • 通过 @ConfigurationProperties 注解,声明将 server 前缀的配置项,设置到 ServerProperties配置属性类中。

< 3.2>、< 3.3> 处,在创建 TomcatWebServerFactoryCustomizer 和 JettyWebServerFactoryCustomizer 对象时,都会将 ServerProperties 传入其中,作为后续创建的 Web 服务器的配置。也就是说通过修改在配置文件的配置项,就可以自定义 Web 服务器的配置。
结论三:通过配置属性,可以解决“创建的 Bean 的属性?”的问题。

2. 自动配置类

  1. Spring Boot 的 spring-boot-autoconfigure 项目,提供了大量框架的自动配置
  2. 通过 SpringApplication#run(Class<?> primarySource, String… args)方法,启动 Spring Boot 应用的时候,有个非常重要的组件 SpringFactoriesLoader 类,会读取META-INF 目录下的 spring.factories 文件,获得每个框架定义的需要自动配置的配置类。
  3. spring-boot-autoconfigure 项目提供的是它选择的主流框架的自动配置,所以其它框架需要自己实现。

3. 条件注解

在 Spring3.1 版本时,为了满足不同环境注册不同的 Bean ,引入了 @Profile 注解。

@Configuration
public class DataSourceConfiguration {

    @Bean
    @Profile("DEV")
    public DataSource devDataSource() {
        // ... 单机 MySQL
    }

    @Bean
    @Profile("PROD")
    public DataSource prodDataSource() {
        // ... 集群 MySQL
    }
    
}
  • 在测试环境下,注册单机 MySQL 的 DataSource Bean。
  • 在生产环境下,注册集群 MySQL 的 DataSource
    Bean。

在 Spring4 版本时,提供了 @Conditional 注解,用于声明在配置类或者创建 Bean 的方法上,表示需要满足指定条件才能生效

@Configuration
public class TestConfiguration {
    @Bean
    @Conditional(XXXCondition.class) // XXXCondition: 实现Condition 接口,提供具体的条件实现。
    public Object xxxObject() {
        return new Object();
    }
}
  • @ConditionalOnBean:当容器里有指定 Bean 的条件下
  • @ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下
  • @ConditionalOnSingleCandidate:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选 Bean
  • @ConditionalOnClass:当类路径下有指定类的条件下
  • @ConditionalOnMissingClass:当类路径下没有指定类的条件下
  • @ConditionalOnProperty:指定的属性是否有指定的值
  • @ConditionalOnResource:类路径是否有指定的值
  • @ConditionalOnExpression:基于 SpEL 表达式作为判断条件
  • @ConditionalOnJava:基于 Java版本作为判断条件
  • @ConditionalOnJndi:在 JNDI 存在的条件下差在指定的位置
  • @ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下
  • @ConditionalOnWebApplication:当前项目是 Web项 目的条件下

4. 配置属性

Spring Boot 约定读取 application.yaml、application.properties 等配置文件,从而实现创建 Bean 的自定义属性配置,甚至可以搭配 @ConditionalOnProperty 注解来取消 Bean 的创建。

5.自定义 Starter

在一些场景下,需要实现自定义 Starter 来达到自动配置的目的。例如说:

  • 三方框架并没有提供 Starter,比如说 Swagger、XXL-JOB 等。
  • Spring Boot 内置的 Starter 无法满足自己的需求,比如说 spring-boot-starter-jdbc 不提供多数据源的配置。
    在这里插入图片描述
    命名规则
    在这里插入图片描述

5.1 yunai-server-spring-boot-starter 项目

5.1.1 引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>lab-47</artifactId>
        <groupId>cn.iocoder.springboot.labs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>yunai-server-spring-boot-starter</artifactId>

    <dependencies>
        <!-- 引入 Spring Boot Starter 基础库 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>
    </dependencies>

</project>

5.1.2 YunaiServerProperties

在 cn.iocoder.springboot.lab47.yunaiserver.autoconfigure 包下,创建 YunaiServerProperties 配置属性类,读取 yunai.server 前缀的配置项。代码如下:

@ConfigurationProperties(prefix = "yunai.server")
public class YunaiServerProperties {

    /**
     * 默认端口
     */
    private static final Integer DEFAULT_PORT = 8000;

    /**
     * 端口
     */
    private Integer port = DEFAULT_PORT;

    public static Integer getDefaultPort() {
        return DEFAULT_PORT;
    }

    public Integer getPort() {
        return port;
    }

    public YunaiServerProperties setPort(Integer port) {
        this.port = port;
        return this;
    }

}

5.1.3 YunaiServerAutoConfiguration

在 cn.iocoder.springboot.lab47.yunaiserver.autoconfigure 包下,创建 YunaiServerAutoConfiguration 自动配置类,在项目中存在 com.sun.net.httpserver.HttpServer 类时,创建 HttpServer Bean,并启动该服务器。代码如下:

@Configuration // 声明配置类
@EnableConfigurationProperties(YunaiServerProperties.class) // 使 YunaiServerProperties 配置属性类生效
public class YunaiServerAutoConfiguration {

    private Logger logger = LoggerFactory.getLogger(YunaiServerAutoConfiguration.class);

    @Bean // 声明创建 Bean
    @ConditionalOnClass(HttpServer.class) // 需要项目中存在 com.sun.net.httpserver.HttpServer 类。该类为 JDK 自带,所以一定成立。
    public HttpServer httpServer(YunaiServerProperties serverProperties) throws IOException {
        // 创建 HttpServer 对象,并启动
        HttpServer server = HttpServer.create(new InetSocketAddress(serverProperties.getPort()), 0);
        server.start();
        logger.info("[httpServer][启动服务器成功,端口为:{}]", serverProperties.getPort());

        // 返回
        return server;
    }
}

5.1.4 spring.factories

在 resources 目录下创建,创建 META-INF 目录,然后在该目录下创建 spring.factories 文件,添加自动化配置类为 YunaiServerAutoConfiguration。内容如下:

rg.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.springboot.lab47.yunaiserver.autoconfigure.YunaiServerAutoConfiguration

5.2 lab-47-demo 项目

5.2.1 引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>lab-47</artifactId>
        <groupId>cn.iocoder.springboot.labs</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-47-demo</artifactId>

    <dependencies>
        <!-- 引入自定义 Starter -->
        <dependency>
            <groupId>cn.iocoder.springboot.labs</groupId>
            <artifactId>yunai-server-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

5.2.2 配置文件

在 resource 目录下,创建 application.yaml 配置文件,设置 yunai.server.port 配置项来自定义 HttpServer 端口。配置如下:

yunai:
  server:
    port: 8888 # 自定义 HttpServer 端口

5.2.3 DemoApplication

创建 DemoApplication.java 类,配置 @SpringBootApplication 注解即可。代码如下:

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

5.2.4 测试

执行 DemoApplication#main(String[] args) 方法,启动 Spring Boot 应用。打印日志如下:

2020-02-02 13:03:12.156  INFO 76469 --- [           main] c.i.s.lab47.demo.DemoApplication         : Starting DemoApplication on MacBook-Pro-8 with PID 76469 (/Users/yunai/Java/SpringBoot-Labs/lab-47/lab-47-demo/target/classes started by yunai in /Users/yunai/Java/SpringBoot-Labs)
2020-02-02 13:03:12.158  INFO 76469 --- [           main] c.i.s.lab47.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2020-02-02 13:03:12.873  INFO 76469 --- [           main] c.i.s.l.y.a.YunaiServerAutoConfiguration : [httpServer][启动服务器成功,端口为:8888]
2020-02-02 13:03:12.927  INFO 76469 --- [           main] c.i.s.lab47.demo.DemoApplication         : Started DemoApplication in 1.053 seconds (JVM running for 1.47)
  • YunaiServerAutoConfiguration 成功自动配置 HttpServer Bean,并启动该服务器在 8888 端口

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

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

相关文章

SV-9032 机架式ip网络采播器

SV-9032是深圳锐科达电子有限公司的一款机架式网络采播器&#xff0c;具有10/100M以太网接口&#xff0c;后面板上有一组AUX音源输入和一组6.35mm接口的麦克风输入&#xff0c;可以直接连接音源输出设备或麦克风&#xff0c;将采集音源编码后发送至网络播放终端上。同时还具有三…

了解 WebSocket 和 TCP :有何不同

WebSocket — 双向通讯的艺术 简要概述 WebSocket 代表着WebSocket通讯协议&#xff0c;提供了一条用于客户端和服务器间实现实时、双向、全双工通信的渠道。在WebSocket引入之前&#xff0c;网页应用的数据更新依赖于频繁的轮询&#xff0c;这种做法不仅效率低下&#xff0c;…

Web实战丨基于Django的简单网页计数器

文章目录 写在前面Django简介主要程序运行结果系列文章写在后面 写在前面 本期内容 基于django的简单网页计数器 所需环境 pythonpycharm或vscodedjango 下载地址 https://download.csdn.net/download/m0_68111267/88795604 Django简介 Django 是一个用 Python 编写的高…

第十四届蓝桥杯大赛软件赛省赛(C/C++ 大学B组)题解

尝试再做一次&#xff0c;我记得还是有点难&#xff0c;我会尽量多写一点解析&#xff0c;尽量让基础比较弱的友友也能看懂&#xff0c;希望能给你带来帮助 目录 1. 日期统计 题目描述 解题思路 具体代码 2. 01 串的熵 题目描述 解题思路 具体代码 3. 冶炼金属 题目…

正点原子--STM32中断系统学习笔记(2)

引言 上篇帖子STM32中断系统学习笔记(1)是理论&#xff0c;这篇帖子开始实战&#xff0c;目标是通过按键实现LED的控制。 1.工程建立 以正点原子HAL库 实验1 跑马灯实验为基础&#xff0c;复制工程&#xff0c;在“Drivers--BSP”目录下建立EXTI文件夹&#xff0c;并创建ext…

2024美国大学生数学建模竞赛A-F题完整思路+配套代码数据+后续高质量参考论文更新

The Mathematical Contest in Modeling (MCM) The Interdisciplinary Contest in Modeling (ICM) 24美赛【完整每问手把手详细思路可修改50页多种思路版本word版保奖论文】配套升级求解代码可视化图表 美赛A-F题完整版获取见文末 下文包含&#xff1a;2024美国大学生数学建模…

美区或其他外区Appstore账号AppleID注册教程,简单快速,苹果必备!

▍前言 现在越来越多的APP在国区APPstore下架&#xff0c;如果想有更好的使用体验&#xff0c;不得不去外区下载APP&#xff0c;那就需要一个外区的apple id&#xff0c;注册也很简单&#xff0c;今天大鹏通过电脑ipad给大家注册一个&#xff0c;建议大家直接使用iPhone或者iPa…

JVM性能分析工具——Arthas及火焰图的使用

Arthas的使用 Arthas常用命令Arthas的安装Linux压测工具Apache Bench安装火焰图的使用火焰图如何分析火焰图的互动 Arthas常用命令 help &#xff1a;查看所有命令dashboard &#xff1a;仪表板&#xff0c;查看线程的CPU信息等heapdump &#xff1a;不同类对象占用内存比重&a…

【微服务核心】Spring Cloud

文章目录 1. 简介2. 微服务项目搭建2.1 父工程2.2 提供者子工程2.3 热部署配置2.4 消费者子工程2.5 项目重构 3. 服务注册与发现3.1 Eureka 服务注册与发现3.1.1 单机版工程搭建3.1.2 单机版改集群版3.1.3 服务发现3.1.4 保护模式 3.2 ZooKeeper 服务注册与发现3.3 Consul 服务…

【五】【C++】类与对象(三)

const只读 在 C 中&#xff0c;const 关键字用于声明一个变量为常量&#xff0c;意味着一旦被初始化之后&#xff0c;它的值就不能被改变。 声明常量&#xff1a; 使用 const 关键字可以声明变量为常量。这意味着这个变量的值不能被修改。 const int MAX_SIZE 100; 指针与…

【江科大】STM32:MPU6050介绍

文章目录 MPU6050介绍结构图MPU6050参数硬件电路模块内部结构框图数据帧格式寄存器地址 MPU6050介绍 MPU6050是一个6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的加速度、角速度参数&#xff0c;通过数据融合&#xff0c;可进一步得到姿态角&#xff0c;常应用于平衡…

【智慧工业】东胜物联定位与跟踪解决方案,为方案商提供蓝牙网关、信标等物联网智能硬件设备

利用东胜物联的蓝牙网关我们的合作伙伴在德国的建筑工地成功实施了基于物联网蓝牙的员工出勤和跟踪管理解决方案&#xff0c;该解决方案简化了员工时间表并增强了工作流程&#xff0c;为经理和主管提供了更多时间来专注于项目洞察&#xff0c;并提高了员工的效率、绩效和生产力…

C++引用、内联函数、auto关键字介绍以及C++中无法使用NULL的原因

文章目录 一、引用1.1 引用概念1.2 引用特性1.3 常引用1.4 使用场景1.4.1 做参数1.4.2做返回值 1.5 引用和指针的区别1.6 小结一下 二、内联函数2.1 内联的概念2.2 内联的特性2.3 【面试题】 三、auto关键字(C11)3.1 类型别名思考3.2 auto简介 四、auto的使用细则4.1 基于范围的…

Linux系统——防火墙

一、防火墙的认识 引言 安全技术 入侵检测系统&#xff08;Intrusion Detection Systems&#xff09;&#xff1a;特点是不阻断任何网络访问&#xff0c;量化、定位来自内外网络的威胁情况&#xff0c;主要以提供报警和事后监督为主&#xff0c;提供有针对性的指导措施和安全…

假期刷题打卡--Day20

1、MT1173魔数 一个数字&#xff0c;把他乘以二&#xff0c;会得到一个新的数字&#xff0c;如果这个新数字依然由原数中那些数字组成&#xff0c;就称原数为一个魔数。输入正整数N&#xff0c;检查它是否是一个魔数&#xff0c;输出YES或者NO。 格式 输入格式&#xff1a; …

SpringBoot RestTemplate 设置挡板

项目结构 代码 BaffleConfig /*** Description 记录配置信息* Author wjx* Date 2024/2/1 14:47**/ public interface BaffleConfig {// 是否开启挡板的开关public static boolean SWITCH true;// 文件根目录public static String ROOT_PATH "D:\\TIS\\mock";// …

ElementUI Form:Select 选择器

ElementUI安装与使用指南 Select 选择器 点击下载learnelementuispringboot项目源码 效果图 el-select.vue&#xff08;Select选择器&#xff09;页面效果图 项目里el-select.vue代码 <script> export default {name: el_select,data() {return {options: [{value…

LeetCode刷题:使用栈解决150. 逆波兰表达式求值

给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&#xff1a; 有效的算符为 、-、* 和 / 。每个操作数&#xff08;运算对象&#xff09;都可以是一个整数或者另一个表达式。两个…

泰迪智能科技大模型微调项目训练营已开营

泰迪智能科技大模型微调项目训练营开营 跟张良均老师学大数据人工智能 项目一&#xff1a;医疗诊疗对话意图识别 项目二&#xff1a;中医问答系统 项目三&#xff1a;某平台股票评论情感识别 学习流程&#xff1a; 项目一&#xff1a;医疗诊疗对话…

validator 对象校验,自定义校验实现

一、导入validator工具需要的jar包 <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>4.1.0.Final</version></dependency><dependency><groupId>javax.valid…
最新文章