第2章——springboot核心机制


一、为何以继承方式引入SpringBoot

1.提出疑问

以前我们在开发项目时,需要什么,引入对应的依赖就行,比如我们需要连接mysql数据,则引入mysql驱动的依赖,如下:

<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.3.0</version>
</dependency>

现在我们要使用SpringBoot框架,按说也应该采用依赖的方式将SpringBoot框架引入,如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version>
</dependency>

但是SpringBoot官方推荐的不是直接引入依赖,而是采用继承的方式实现,如下:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version>
</parent>

为什么

2.作为父项目和作为依赖的区别

继承父工程的优势

  • 依赖管理:可以在父工程中定义依赖的版本,子模块可以直接引用而不必指定版本号。

  • 插件管理:可以在父工程中配置常用的插件及其版本,子模块可以直接使用这些配置。

  • 属性设置:可以在父工程中定义一些通用的属性,如项目编码、Java 版本等。

  • 统一配置:可以统一多个子模块的构建配置,确保一致性。

直接引入依赖的局限性(如果你不使用继承父工程的方式,而是通过直接引入依赖的方式来管理项目,那么你将失去上述的一些优势)

  • 依赖版本管理:每个子模块都需要单独指定依赖的版本,这会导致大量的重复配置,并且难以维护。

  • 插件配置:每个子模块都需要单独配置插件及其版本,无法共享父工程中的插件配置。

  • 属性设置:每个子模块都需要单独设置通用的属性,如项目编码、Java 版本等。

  • 构建配置:每个子模块的构建配置需要单独维护,难以保证一致性。

总结:选择哪种方式取决于你的具体需求。

  • 如果你希望多个项目之间共享构建配置,那么使用父项目是一个好的选择;

  • 如果你只是想在项目之间共享代码,那么应该使用依赖关系。

3.原理揭晓

通过源码来分析一下:


通过上图源码可以看到Spring Boot预先对开发中需要用到的依赖进行了版本的统一管理。我们需要和SpringBoot框架共享这个构建配置。因此官方推荐使用继承的方式引入SpringBoot框架。

3.依赖统一管理的好处

Spring Boot 框架的一个重要特性就是简化了项目依赖管理。它通过提供一个叫做“依赖管理”的功能来帮助开发者更容易地管理和使用第三方库和其他 Spring 组件。具体来说,Spring Boot 提供了一个包含多个 Spring 和其他常用库的依赖版本配置文件(通常是在 spring-boot-dependencies 文件中),这使得开发者不需要在自己的项目中显式指定这些依赖的版本号。

这样做有以下几个好处:

  • 简化依赖声明: 开发者只需要在 pom.xml 文件中声明需要的依赖而不需要指定其版本号,因为 Spring Boot 已经为这些依赖指定了版本。例如,如果你需要使用mysql驱动,你只需要添加相应的依赖声明而不需要关心版本。

<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId>
</dependency>
  • 避免版本冲突: 当多个库之间存在依赖关系的时候,如果手动管理版本可能会导致版本之间的冲突(即“依赖地狱”)。Spring Boot 提供的统一版本管理可以减少这种冲突的可能性。

  • 易于升级: 当 Spring Boot 发布新版本时,通常会更新其依赖库到最新稳定版。因此,当你升级 Spring Boot 版本时,它所管理的所有依赖也会随之更新到兼容的版本。

  • 减少配置错误: 由于 Spring Boot 自动处理了依赖的版本,减少了手动输入版本号可能引入的拼写或格式错误。

  • 提高开发效率: 开发者可以专注于业务逻辑的编写,而不是花费时间在解决依赖问题上。

总的来说,Spring Boot 的依赖管理功能使得开发者可以更加专注于业务逻辑的实现,同时减少了因依赖版本不一致而引发的问题,提高了项目的可维护性和开发效率。


当然,如果你在项目中需要更改某个依赖的版本号,不想使用SpringBoot框架指定的版本号,只需要在引入依赖时强行执行版本号即可,maven是支持就近原则的:

这样做就是采用SpringBoot指定版本的依赖:

<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId>
</dependency>

这样做就是不采用SpringBoot指定版本的依赖:

<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.2.0</version>
</dependency>

二、Starter-启动器

在 Spring Boot 中,启动器(Starter)本质上是一个简化依赖管理的概念。

Spring Boot 的启动器本质上就是一组预定义的依赖集合,它们被组织成一个个 Maven的依赖,以方便开发者快速集成特定的功能模块。

如果你想做web开发,只需要引入web启动器。web启动器会自动引入web开发所需要的子依赖。

1.启动器实现原理

  1. 依赖聚合: 每个启动器通常对应一个特定的功能集或者一个完整的应用模块,如 spring-boot-starter-web 就包含了构建 Web 应用所需的所有基本依赖项,如 Spring MVC, Tomcat 嵌入式容器等。

  2. 依赖传递: 当你在项目中引入一个启动器时,它不仅会把自身作为依赖加入到你的项目中,还会把它的所有直接依赖项(transitive dependencies)也加入进来。这意味着你不需要单独声明这些依赖项,它们会自动成为项目的一部分。

  3. 版本管理: 启动器内部已经指定了所有依赖项的具体版本,这些版本信息存储在一个公共的 BOM(Bill of Materials,物料清单)文件中,通常是 spring-boot-dependencies。当引入启动器时,实际上也间接引用了这个 BOM,从而确保了所有依赖项版本的一致性。

  4. 自动配置: 许多启动器还提供了自动配置(Auto-configuration),这是一种机制,允许 Spring Boot 根据类路径上的可用组件自动设置你的应用程序。例如,如果类路径上有 Spring MVC 和嵌入式 Tomcat,则 Spring Boot 会自动配置它们,并准备好一个 web 应用程序。

使用启动器的示例

假设你想创建一个基于 Spring MVC 的 RESTful Web 应用,你可以简单地将 spring-boot-starter-web 添加到你的项目中:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

当你添加这个依赖时,Spring Boot 会处理所有必要的细节,包括添加 Spring MVC 和 Tomcat 作为嵌入式 Servlet 容器,并且根据类路径上的内容进行适当的自动配置。如下图所示:

这就是 Spring Boot 启动器的基本实现原理,它简化了依赖管理,让开发者能够更专注于业务逻辑的实现。

2.都有哪些启动器

启动器通常包括:

  • SpringBoot官方提供的启动器

  • 非官方提供的启动器

官方提供的启动器

启动器命名特点:spring-boot-starter-*

非官方的启动器

启动器命名特点:*-spring-boot-starter

三、Spring Boot核心注解

创建一个新的模块,来学习Spring Boot核心注解:

1.@SpringBootApplication注解

Spring Boot的主入口程序被@SpringBootApplication注解标注,可见这个注解的重要性,查看它的源码:

可以看出这个注解属于组合注解。拥有@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan的功能。

2.@SpringBootConfiguration注解

@SpringBootConfiguration注解的源码如下:

可以看到这个注解的被@Configuration标注,说明主入口程序是一个配置类。也就是说主入口中的方法可以被@Bean注解标注,被@Bean注解的标注的方法会被Spring容器自动调用,并且将该方法的返回对象纳入IoC容器的管理。

SpringBoot主入口类实际上就是一个配置类

这个配置类也可以称为,起源的意思,SpringBoot从这个配置类开始加载项目中所有的bean。

3.@EnableAutoConfiguration注解

该注解表示`启用自动配置`

Spring Boot 会根据你引入的依赖自动为你配置好一系列的 Bean,无需手动编写复杂的配置代码。

例如:如果你在SpringBoot项目中进行了如下配置:

关于 @EnableAutoConfiguration 注解:启用自动配置。也就是说默认情况下,springboot应用都会默认启用自动配置。自动配置有什么用?所谓的自动配置只要启动,springboot应用会去类路径当中查找class,根据类路径当中有某个类,或某些类,来自动管理bean,不需要我们程序员手动配置。比如:springboot检测到类路径当中有 SqlSessionFactory,或者在application.properties文件中配置了数据源,那么springboot会认为项目中有mybatis框架,因此会将mybatis中相关的bean自动初始化,然后放到IoC容器当中,自动将这些bean管理起来。sqlSessionFactorytransactionManager

并且在依赖中引入了mybatis依赖/mybatis启动器,那么SpringBoot框架将为你自动化配置以下bean:

  • SqlSessionFactory: MyBatis的核心工厂SqlSessionFactory会被自动配置。这个工厂负责创建SqlSession实例,后者用来执行映射文件中的SQL语句。

  • TransactionManager: DataSourceTransactionManager会被自动配置来管理与数据源相关的事务。

4.@ComponentScan注解

这个注解的作用是:启动组件扫描功能,代替spring框架xml文件中这个配置:

<context:component-scan base-package="com.powernode.sb305core"/>

因此被`@SpringBootApplication`注解标注之后,会启动组件扫描功能,扫描的包是`主入口程序所在包及子包`,因此如果一个bean要纳入IoC容器的管理则必须放到主入口程序所在包及子包下。放到主入口程序所在包之外的话,扫描不到。测试一下:


结论:要让bean纳入IoC容器的管理,必须将类放到主入口程序同级目录下,或者子目录下。

四、Spring Boot的单元测试

1.不使用单元测试怎么调用service

User

package org.example1.springboot03.bean;public class User {private String username;private String password;@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';}public User(String username, String password) {this.username = username;this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

service:

入口:

测试:

2.使用单元测试怎么调用service

⑴.test-starter引入以及测试类编写

使用单元测试应该如何调用service对象上的方法呢?

在使用脚手架创建Spring Boot项目时,为我们生成了单元测试类,如下:

要使用单元测试,需要引入单元测试启动器,如果使用脚手架创建SpringBoot项目,这个test启动器会自动引入:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

⑵.@SpringBootTest注解

@SpringBootTest 会创建一个完整的 Spring 应用程序上下文(Application Context),这个上下文包含了应用程序的所有组件和服务。以下是 @SpringBootTest 做的一些主要工作:

  1. 创建 ApplicationContext

    • @SpringBootTest 使用 SpringApplicationrun() 方法来启动一个 Spring Boot 应用程序上下文。这意味着它会加载应用程序的主配置类和其他相关的配置类。

  2. 加载配置文件

    • 它会查找并加载默认的配置文件,如 application.properties

  3. 自动配置

    • 如果应用程序依赖于 Spring Boot 的自动配置特性,@SpringBootTest 会确保这些自动配置生效。这意味着它会根据可用的类和bean来自动配置一些组件,如数据库连接、消息队列等。

  4. 注入依赖

    • 使用 @SpringBootTest 创建的应用程序上下文允许你在测试类中使用 @Autowired 注入需要的 bean,就像在一个真实的 Spring Boot 应用程序中一样。

总的来说,@SpringBootTest 为你的测试提供了尽可能接近实际运行时环境的条件,这对于验证应用程序的行为非常有用。

测试结果如下:

五、外部化配置

1.什么是外部化配置

外部化配置是指:将配置信息存储在应用程序代码之外的地方。这样配置信息可以独立于代码进行管理。这样方便了配置的修改,并且修改后不需要重新编译代码,也不需要重新部署项目。

⑴.外部化配置的方式

SpringBoot支持多种外部化配置方式,包括但不限于:

  • properties文件

  • YAML文件

  • 系统环境变量

  • 命令行参数

  • ......

⑵.外部化配置的优势

  1. 灵活性:配置文件可以独立于应用程序部署,这使得可以根据运行环境的不同来调整配置,而无需修改代码。

  2. 易于维护:配置变更不需要重新构建和部署应用程序,降低了维护成本。

  3. 安全性:敏感信息如数据库密码、API密钥等可以存储在外部,并且可以限制谁有权限访问这些配置信息。

  4. 共享性:多实例或多服务可以共享相同的配置信息,减少重复配置的工作量。

  5. 版本控制:配置文件可以存放在版本控制系统中,便于跟踪历史版本和回滚配置。

总之,外部化配置使得配置更加灵活、安全、易于管理和共享,是现代云原生应用中非常推荐的做法

⑶.外部化配置对比传统配置

在传统的SSM三大框架中,如果修改XML的配置后,需要对应用重新打包,重新部署。

使用SpringBoot框架的外部化配置后,修改配置后,不需要对应用重新打包,也不需要重新部署,最多重启一下服务即可。

2.application.properties

application.properties配置文件是SpringBoot框架默认的配置文件。

application.properties不是必须的,SpringBoot对于应用程序来说,都提供了一套默认配置(就是我们所说的自动配置)。

如果你要改变这些默认的行为,可以在application.properties文件中进行配置。

application.properties可以放在类路径当中,也可以放在项目之外。因此称为外部化配置。

Spring Boot 框架在启动时会尝试从以下位置加载 application.properties 配置文件:


Spring Boot 加载application.properties或application.yml配置文件的位置顺序。


Spring Boot 会按照这个顺序来加载配置文件,如果在多个位置有相同的属性定义,那么最先检查的位置中的属性值将优先使用。

如果你想要指定其他的配置文件位置或者改变默认的行为,可以通过 --spring.config.location= 后跟路径的方式来指定配置文件的具体位置。例如 :

java -jar sb3-01-first-web-1.0-SNAPSHOT.jar 
--spring.config.location=file:///E:\a\b\application.properties

这样,Spring Boot 将会首先从 E:\a\b\ 这个路径加载配置文件。注意,这种方式可以用来覆盖默认的配置文件位置,并且可以结合以上提到的位置一起使用。

注意:以上的--spring.config.location=file:///E:\a\b\application.properties就属于命令行参数,它将来会被传递到main方法的(String[] args)参数上。

3.使用@Value注解

@Value注解可以将application.properties/application.yml文件中的配置信息注入/绑定到java对象的属性上。

语法格式:@Value("${key}")

使用脚手架创建SpringBoot项目,不添加任何启动器:

使用@Value注解时也可以指定默认值,当指定默认值时,如果配置文件中没有指定配置值,则采用默认值。

语法格式:@Value("${key:defalut}")

@Service("userService")
public class UserService {@Value("${myapp.username}")private String username;@Value("${myapp.email}")private String email;@Value("${myapp.age}")private Integer age;@Value("${myapp.password:123456}")private String password;public void printInfo(){String str = String.join(",", username, email, String.valueOf(age), password);System.out.println(str);}
}

4.YAML

YAML概述

SpringBoot采用集中式配置管理,所有的配置都编写到一个配置文件中:application.properties

如果配置非常多,层级不够分明,因此SpringBoot为了提高配置文件可读性,也支持YAML格式的配置文件:application.yml

YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化格式,它通常用于配置文件,在各种编程语言中作为一种存储或传输数据的方式。YAML的设计目标是易于阅读和编写,同时保持足够的表达能力来表示复杂的数据结构。

YAML文件的扩展名可以是.yaml.yml

常见的数据存储和交换格式

propertiesXMLJSONYAML这几种格式确实是用来存储和交换数据的常见方式,但它们各有特点和适用场景:

Properties

  • 这种格式主要用于Java应用程序中的配置文件。它是键值对的形式,每一行是一个键值对,使用等号或冒号分隔键和值。

  • 特点是简单易懂,但在处理复杂结构的数据时显得力不从心。

XML (eXtensible Markup Language)

  • XML是一种标记语言,用来描述数据的格式。它支持复杂的数据结构,包括嵌套和属性。

  • XML文档具有良好的结构化特性,适合传输和存储结构化的数据。但是,XML文档通常体积较大,解析起来也比较耗资源。

JSON (JavaScript Object Notation)

  • JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,支持多种数据类型,如数字、字符串、布尔值、数组和对象。

  • JSON因为简洁和高效而广泛应用于Web应用程序之间进行数据交换。

YAML (YAML Ain't Markup Language)

  • YAML设计的目标之一就是让人类更容易阅读。它支持类似JSON的数据序列化,但提供了更多的灵活性,例如缩进来表示数据结构。

  • YAML非常适合用来编写配置文件,因为它允许以一种自然的方式组织数据,并且可以包含注释和其他人类可读的元素。

总结来说,这四种格式都可以用来存储和交换数据,但它们的设计初衷和最佳使用场景有所不同。选择哪种格式取决于具体的应用需求、数据复杂度、性能要求等因素。

YAML的语法规则

YAML的语法规则如下:

  1. 数据结构:YAML支持多种数据类型,包括:

    1. 字符串、数字、布尔值

    2. 数组、list集合

    3. map键值对 等。

  2. YAML使用一个空格来分隔属性名属性值,例如:

    1. properties文件中这样的配置:name=jack

    2. yaml文件中需要这样配置:name: jack

  3. YAML用换行+空格来表示层级关系。注意不能使用tab,必须是空格,空格数量无要求,大部分建议2个或4个空格。例如:

    1. properties文件中这样的配置:myapp.name=mall

    2. yaml文件中就需要这样配置:

myapp:name: mall

4.同级元素左对齐。

         1.例如: properties文件中有这样的配置:

myapp.name=mall
myapp.count=10

          2. `yaml`文件中就应该这样配置:

myapp:name: mallcount: 10

5.键必须是唯一的:在一个映射中,键必须是唯一的。

6.注释:使用#进行注释。

7.大小写敏感

YAML的使用小细节

第一:普通文本也可以使用单引号或双引号括起来:(当然普通文本也可以不使用单引号和双引号括起来。)

  • 单引号括起来:单引号内所有的内容都被当做普通文本,不转义(例如字符串中有\n,则\n被当做普通的字符串)

  • 双引号括起来:双引号中有 \n 则会被转义为换行符

第二:保留文本格式

  • | 将文本写到这个符号的下层,会自动保留格式。

第三:文档切割

  • --- 这个符号下面的配置可以认为是一个独立的yaml文件。便于庞大文件的阅读。

# 普通文本引号使用示例
# 不使用引号
plainTextNoQuotes: 这是一段普通文本
# 使用单引号
plainTextSingleQuotes: '这是一段包含 \n 的普通文本,\n 不会被转义'
# 使用双引号
plainTextDoubleQuotes: "这是一段包含 \n 的普通文本,\n 会被转义为换行符"# 保留文本格式示例
preserveFormat: |这是一段保留格式的文本。它会按照这里的格式进行显示。每行内容都会保持原有的换行。# 文档切割示例
---
# 这部分配置可以认为是一个独立的yaml文件
newDocument:key1: value1key2: value2
---
# 又一个独立的配置文档
anotherDocument:item1: 123item2: 456

application.yml

Spring Boot框架同时支持propertiesyaml

在 Spring Boot 里,当同一个目录下同时存在application.propertiesapplication.yml文件时,application.properties文件会被优先解析。

resources/config目录下新建application.yml文件,进行如下配置:



5.配置文件合并

一个项目中所有的配置全部编写到application.properties文件中,会导致配置臃肿,不易维护,有时我们会将配置编写到不同的文件中,例如:

application-mysql.properties专门配置mysql的信息,

application-redis.properties专门配置redis的信息,最终将两个配置文件合并到一个配置文件中。

properties文件

创建配置文件

src/main/resources目录下创建以下三个配置文件:

application.properties

spring.config.import=application-mysql.properties,application-redis.properties

这里使用spring.config.import属性来引入其他配置文件,多个文件之间用逗号分隔。

application-mysql.properties

mysql.host=localhost
mysql.port=3306
mysql.username=root
mysql.password=password

此文件用于配置 MySQL 相关信息。

application-redis.properties

redis.host=localhost
redis.port=6379
redis.password=redis_password

这个文件用于配置 Redis 相关信息。


yaml文件

application-mysql.yml

spring:datasource:username: rootpassword: 789789

application-redis.yml

spring:data:redis:host: localhostport: 6379

application.yml

spring:config:import:- classpath:application-mysql.yml- classpath:application-redis.yml

6.多环境切换

在Spring Boot中,多环境切换是指在一个应用程序中支持多种运行环境配置的能力。这通常用于区分开发(development)、测试(testing)、预生产(staging)和生产(production)等不同阶段的环境。

这种功能使得开发者能够在不同的环境中使用不同的配置,比如数据库连接信息、服务器端口、环境变量等,而不需要更改代码。这对于维护一个可移植且易于管理的应用程序非常重要。

开发环境的配置文件名一般叫做:application-dev.properties

spring.datasource.username=dev
spring.datasource.password=dev123
spring.datasource.url=jdbc:mysql://localhost:3306/dev

测试环境的配置文件名一般叫做:application-test.properties

spring.datasource.username=test
spring.datasource.password=test123
spring.datasource.url=jdbc:mysql://localhost:3306/test

预生产环境的配置文件名一般叫做:application-preprod.properties

spring.datasource.username=preprod
spring.datasource.password=preprod123
spring.datasource.url=jdbc:mysql://localhost:3306/preprod

生产环境的配置文件名一般叫做:application-prod.properties

spring.datasource.username=prod
spring.datasource.password=prod123
spring.datasource.url=jdbc:mysql://localhost:3306/prod

如果你希望该项目使用生产环境的配置,你可以这样做:

第一种方式:在 application.properties 文件中添加配置

在 application.properties 文件里添加以下内容:

spring.profiles.active=prod

第二种方式:在命令行参数上添加配置

假设你运用的是 Java 程序,以下是启动时添加命令行参数的示例:

java -jar your-application.jar --spring.profiles.active=prod

若你使用的是 Maven 来运行项目,示例如下:

mvn spring-boot:run -Dspring-boot.run.arguments=--spring.profiles.active=prod

要是你运用的是 Gradle 来运行项目,示例如下:

gradle bootRun --args='--spring.profiles.active=prod'

7.将配置绑定到bean

绑定简单bean

SpringBoot配置文件中的信息除了可以使用@Value注解读取之外,也可以将配置信息一次性赋值给Bean对象的属性。

例如有这样的配置:

Bean需要这样定义:

说明:

1.被绑定的bean,需要使用@ConfigurationProperties(prefix = "app")注解进行标注,prefix用来指定前缀

bean中的所有属性都提供了setter方法。因为底层是通过setter方法给bean属性赋值的。

2.这样的bean需要使用@Component注解进行标注,纳入IoC容器的管理。@Component注解负责创建Bean对象,@ConfigurationProperties(prefix = "app")注解负责给bean对象的属性赋值。

3.bean的属性需要是非static的属性。

编写测试程序,将bean对象输出,结果如下:

@Configuration注解

以上操作中使用了@Component注解进行了标注,来纳入IoC容器的管理。也可以使用另外一个注解@Configuration,用这个注解将Bean标注为配置类。多数情况下我们会选择使用这个注解,因为该Bean对象的属性对应的就是配置文件中的配置信息,因此这个Bean我们也可以将其看做是一个配置类。

绑定嵌套bean

当一个Bean中嵌套了一个Bean,这种情况下可以将配置信息绑定到该Bean上吗?当然可以。

有这样的一个配置:

需要编写这样的两个Bean:

执行测试程序,结果如下:

@EnableConfigurationProperties与@ConfigurationPropertiesScan

AppBean纳入IoC容器的管理,之前我们说了两种方式:第一种是使用@Component,第二种是使用@Configuration。SpringBoot其实还提供了另外两种方式:

  • 第一种:@EnableConfigurationProperties

  • 第二种:@ConfigurationPropertiesScan

这两个注解都是标注在SpringBoot主入口程序上的:



运行测试:

将配置赋值到Bean的Map/List/Array属性上

代码如下:

package org.example1.springboot310configbindtobean.bean;import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.Arrays;
import java.util.List;
import java.util.Map;@ConfigurationProperties(prefix = "app2.abc")
public class AppBean {// 数组:数组中元素是简单类型private String[] names;// 数组:数组中元素是beanprivate Address[] addrArray;// List集合:集合中的元素是beanprivate List<Address> addrList;// Map集合:String,Beanprivate Map<String, Address> addrs;public void setNames(String[] names) {this.names = names;}public void setAddrArray(Address[] addrArray) {this.addrArray = addrArray;}public void setAddrList(List<Address> addrList) {this.addrList = addrList;}public void setAddrs(Map<String, Address> addrs) {this.addrs = addrs;}@Overridepublic String toString() {return "AppBean{" +"names=" + Arrays.toString(names) +", addrArray=" + Arrays.toString(addrArray) +", addrList=" + addrList +", addrs=" + addrs +'}';}
}

配置信息如下:

测试:


补充yml的写法:

将配置绑定到第三方对象

将配置文件中的信息绑定到某个Bean对象上,如果这个Bean对象没有源码,是第三方库提供的,怎么办?

此时可以单独编写一个方法,在方法上使用以下两个注解进行标注:

  • @Bean

  • @ConfigurationProperties

假设我们有这样一个类Address(假设这个Address是第三方写的,我们无权修改,代码如下:

实现代码如下:

测试代码:

指定数据来源

指定数据的来源用的

之前所讲的内容是将Spring Boot框架默认的配置文件application.propertiesapplication.yml作为数据的来源绑定到Bean上。如果配置信息没有在默认的配置文件中呢?可以使用@PropertySource注解指定配置文件的位置,这个配置文件可以是.properties,也可以是.xml。这里重点掌握.properties即可。

resources目录下新建a目录,在a目录下新建b目录,b目录中新建group-info.properties文件,进行如下的配置:

定义Java类`Group`,然后进行注解标注:

以下三个注解分别起到什么作用:

  • @Configuration:指定该类为配置类,纳入Spring容器的管理

  • @ConfigurationProperties(prefix = "group"):将配置文件中的值赋值给Bean对象的属性

  • @PropertySource("classpath:a/b/group-info.properties"):指定额外的配置文件

编写测试程序,测试结果如下:

8.@ImportResource注解

创建Bean的三种方式总结:

  • 第一种方式:编写applicationContext.xml文件,在该文件中注册Bean,Spring容器启动时实例化配置文件中的Bean对象。

  • 第二种方式:@Configuration注解结合@Bean注解。

  • 第三种方式:@Component、@Service、@Controller、@Repository等注解。

第二种和第三种我们都已经知道了。针对第一种方式,如果在SpringBoot框架中应该怎么实现呢?使用@ImportResource注解实现

定义一个普通的Java类:Person

package org.example1.springboot310configbindtobean.bean;public class Person {private String name;private int age;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

resources目录下新建applicationContext.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="person" class="org.example1.springboot310configbindtobean.bean.Person"><property name="name" value="jackson"/><property name="age" value="20"/></bean></beans>

在SpringBoot主入口类上添加@ImportResource进行资源导入,这样applicationContext.xml文件中的Bean将会纳入IoC容器的管理:

编写测试程序,看看是否可以获取到person这个bean对象:

因此,项目中如果有类似于Spring的这种xml配置文件,要想纳入IoC容器管理,需要在入口类上使用@ImportResource("classpath:applicationContext.xml")注解即可。

9.Environment

SpringBoot框架在启动的时候会将系统配置,环境信息全部封装到Environment对象中,如果要获取这些环境信息,可以调用Environment接口的方法。

在Spring Boot中,Environment接口提供了访问应用程序环境信息的方法,比如活动配置文件、系统环境变量、命令行参数等。Environment接口由Spring框架提供,Spring Boot应用程序通常会使用Spring提供的实现类AbstractEnvironment及其子类来实现具体的环境功能。

Environment对象封装的主要数据包括:

  1. Active Profiles: 当前激活的配置文件列表。Spring Boot允许应用程序定义不同的环境配置文件(如开发环境、测试环境和生产环境),通过激活不同的配置文件来改变应用程序的行为。

  2. System Properties: 系统属性,通常是操作系统级别的属性,比如操作系统名称、Java版本等。

  3. System Environment Variables: 系统环境变量,这些变量通常是由操作系统提供的,可以在启动应用程序时设置特定的值。

  4. Command Line Arguments: 应用程序启动时传递给主方法的命令行参数。

  5. Property Sources: Environment还包含了一个PropertySource列表,这个列表包含了从不同来源加载的所有属性。PropertySource可以来自多种地方,比如配置文件、系统属性、环境变量等。

在Spring Boot中,可以通过注入Environment来获取上述信息。例如:

通过这种方式,你可以根据环境的不同灵活地配置你的应用程序。Environment是一个非常有用的工具,它可以帮助你管理各种类型的配置信息,并根据不同的运行时条件做出相应的调整。

六、Spring Boot中如何进行AOP的开发

1.Spring Boot AOP概述

面向切面编程AOP在Spring教程中已经进行了详细讲解,这里不再赘述,如果忘记的同学,可以重新听一下Spring教程中AOP相关的内容。这里仅带着大家在Spring Boot中实现AOP编程。

Spring Boot的AOP编程和Spring框架中AOP编程的唯一区别是:引入依赖的方式不同。其他内容完全一样。Spring Boot中AOP编程需要引入aop启动器:

<!--aop启动器-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

可以看到,当引入aop启动器之后,会引入aop依赖aspectj依赖

  • aop依赖:如果只有这一个依赖,也可以实现AOP编程,这种方式表示使用了纯Spring AOP实现aop编程。

  • aspectj依赖:一个独立的可以完成AOP编程的AOP框架,属于第三方的,不属于Spring框架。(我们通常用它,因为它的功能更加强大)

2.Spring Boot AOP实现

实现功能:项目中很多service,要求执行任何service中的任何方法之前记录日志。

创建Spring Boot项目引入aop启动器

<!--aop启动器-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

编写service并提供方法

package org.example1.springboot311aop.service;public interface UserService {/*** 保存用户信息* @param id 用户id* @param name 用户名*/void save(Long id, String name);/*** 根据id删除用户* @param id 用户id*/void deleteById(Long id);
}

package org.example1.springboot311aop.service.impl;import org.example1.springboot311aop.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic void save(Long id, String name) {System.out.println("正在保存用户信息:" + name);}@Overridepublic void deleteById(Long id) {System.out.println("正在删除用户" + id + "信息");}
}

编写切面

测试

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

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

相关文章

网络接入服务商查询

要查询网站的 网络接入服务商&#xff08;即网站服务器托管或接入的ISP公司&#xff09;&#xff0c;可以通过以下方法进行查询&#xff1a; 方法1&#xff1a;通过IP地址查询 步骤1&#xff1a;获取网站IP 使用 ping 命令&#xff1a; ping example.com 返回的IP地址即为服务…

超详细!RxSwift 中的 BehaviorRelay 使用教程(含原理 + 示例 + 实战)

目录 前言 1.什么是 BehaviorRelay 2.基本使用方式 3.BehaviorRelay的常用API 4.BehaviorRelay 和其它类型的对比 5.BehaviorRelay的使用场景 1.绑定UITableView 2.MVVM 场景下使用 BehaviorRelay 6.使用注意事项以及建议 1.注意事项 2.使用建议总结 7.推荐阅读 前…

vue-grid-layout实现拖拽修改工作台布局

效果图 vue-grid-layout 文档地址&#xff1a;vue-grid-layout 官网介绍&#xff1a; 使用 // 安装&#xff1a; npm install vue-grid-layout --save// 引用&#xff1a; import { GridLayout, GridItem } from vue-grid-layout// 注册&#xff1a; components:{ GridLay…

windows使用bat脚本激活conda环境

本文不生产技术&#xff0c;只做技术的搬运工&#xff01;&#xff01;&#xff01; 前言 最近需要在windows上使用批处理脚本执行一些python任务&#xff0c;但是被自动激活conda环境给卡住了&#xff0c;研究了一下解决方案 解决方案 call your_conda_path\Scripts\activa…

u-boot学习笔记(四)

文章目录 cmd/sub_cmd/exit.cdo_exit()exit.c可提供的命令及使用方式&#xff1a; ext2.cdo_ext2ls()do_ext2load()ext2.c可提供的命令及使用方式&#xff1a; ext4.cdo_ext4_size()do_ext4_load()do_ext4_ls()do_ext4_write()ext4.c可提供的命令及使用方式&#xff1a; fastbo…

OpenCV 图形API(80)图像与通道拼接函数-----仿射变换函数warpAffine()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 对图像应用仿射变换。 函数 warpAffine 使用指定的矩阵对源图像进行变换&#xff1a; dst ( x , y ) src ( M 11 x M 12 y M 13 , M 21 x M…

《React Native热更新实战:用Pushy打造无缝升级体验》

《React Native热更新实战:用Pushy打造应用“空中加油”,实现无缝升级体验》 写在前面:当你的APP需要"空中加油"时… 想象一下这样的场景:凌晨2点,你的React Native应用刚上线就爆出重大BUG,用户差评如潮水般涌来,应用商店审核至少需要3天…此刻你多么希望能…

《社交应用架构生存战:React Native与Flutter的部署容灾决胜法则》

React Native和Flutter作为当下热门的跨平台开发框架&#xff0c;在社交应用开发领域各显神通。今天&#xff0c;我们深入探索它们在高可用架构中的部署与容灾策略。 React Native凭借其独特优势&#xff0c;在社交应用开发中拥有一席之地。它基于JavaScript和React&#xff0…

网络靶场基础知识

一、网络靶场的核心概念 网络靶场&#xff08;Cyber Range&#xff09;是一种基于虚拟化和仿真技术的网络安全训练与测试平台&#xff0c;通过模拟真实网络环境和业务场景&#xff0c;为攻防演练、漏洞验证、安全测试和人才培养提供安全可控的实验空间。其核心目标是通过“虚实…

AutoGen 框架解析:微软开源的多人 Agent 协作新范式

一、引言 在大语言模型&#xff08;LLM&#xff09;快速发展的今天&#xff0c;复杂任务的自动化协作需求日益增长。微软开源的AutoGen 框架&#xff08;GitHub Star 超 10 万&#xff09;提供了一种基于多智能体对话的协作范式&#xff0c;通过自然语言交互实现多角色 Agent …

极简远程革命:节点小宝 — 无公网IP的极速内网穿透远程解决方案

极简远程革命&#xff1a;节点小宝&#xff0c;让家庭与职场无缝互联 ——打破公网桎梏&#xff0c;重塑数字生活新体验 关键词&#xff1a;节点小宝&#xff5c;内网穿透&#xff5c;P2P直连&#xff5c;家庭网络&#xff5c;企业协作&#xff5c;智能组网节点小宝&#xff5…

【MySQL】存储引擎 - CSV详解

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

云原生安全治理体系建设全解:挑战、框架与落地路径

📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:云原生环境下,安全治理正在被重构 在传统IT架构中,安全防护多依赖边界设备(如防火墙、WAF、堡垒机)进行集中式防护。然而,在云原生环境下,这种“边界式”安全模型正面临颠覆。 应用微服务化…

SiC MOSFET同步Buck DC-DC变换器的宽频混合EMI滤波器设计

摘要由于 SiC MOSFET 在高速开关电源中的广泛应用&#xff0c;导致严重的电磁干扰&#xff08;EMI&#xff09;问题&#xff0c;因此 EMI 滤波器的设计成为研究热点。为了满足电磁兼容&#xff08;EMC&#xff09;标准&#xff0c;无源 EMI 滤波器可以有效地降低 DC-DC 变换器产…

[java八股文][Java并发编程面试篇]场景

多线程打印奇偶数&#xff0c;怎么控制打印的顺序 可以利用wait()和notify()来控制线程的执行顺序。 以下是一个基于这种方法的简单示例&#xff1a; public class PrintOddEven {private static final Object lock new Object();private static int count 1;private stat…

MySQL的索引和事务

目录 1、索引 1.1 查看索引 1.2 创建索引 1.3 删除索引 1.4 索引的实现 2、事务 1、索引 索引等同于目录&#xff0c;属于针对查询操作的一个优化手段&#xff0c;可以通过索引来加快查询的速度&#xff0c;避免针对表进行遍历。 主键、unique和外键都是会自动生成索引的…

Qt 验证自动释放 + 乱码问题(6)

文章目录 验证自动释放&#xff08;对象树上的对象&#xff09;乱码问题的缘由解决乱码问题1. 使用QString2. qDebug() 小结 简介&#xff1a;上一篇文章写到&#xff0c;当new出一个控件对象并且将它挂到对象树上&#xff0c;无需我们手动释放该对象&#xff0c;是因为在一个合…

fastjson2 json.tojsonstring 会自动忽略过滤掉 key: null的数据

如果你想在序列化时保留值为 null 的字段&#xff0c;只要打开 Fastjson2 的 WriteNulls 特性即可。常见做法有两种——按调用级别开启&#xff0c;或全局开启。 1. 在每次序列化时加 WriteNulls import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONWriter…

LeetCode热题100--54.螺旋矩阵--中等

1. 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&#xff1a; 输入&#xff1a;ma…

别卷手柄了!跨平台VR遥操系统实现仿真

我们构建了一个基于 Quest 3 的 VR 遥操系统&#xff0c;该系统能够同时支持 DISCOVERSE 仿真环境与 MMK2 真机的操控&#xff0c;实现了从虚拟环境到真实机器人系统的无缝对接。 • 基于 VR 实现的遥操系统具有良好的扩展性和便携性&#xff0c;为多场景应用提供了灵活的操作方…