1 Spring Boot

Spring Boot 是目前流行的微服务框架倡导约定优先于配置” 其设目的是用来简化新 Spring 应用的初始化搭建以及开发过程。 Spring Boot 提供了很多核心的功能,比如自动化配置 starter(启动器) 简化 Maven 配置、内嵌 Servlet 容器、应用监控等功能,让我们可以快速构建企业级应用程序。

特性:

  • 创建独立的 Spring 应用程序。
  • 嵌入式 Tomcat、 Jetty、 Undertow 容器(jar)
  • 提供的 starters 简化构建配置(简化依赖管理和版本控制)
  • 尽可能自动配置 spring 应用和第三方库
  • 提供生产指标,例如指标、健壮检查和外部化配置
  • 没有代码生成,无需 XML 配置

SpringBoot 同时提供 “开箱即用”,“约定优于配置”的特性。

开箱即用: Spring Boot 应用无需从 0 开始,使用脚手架创建项目。基础配置已经完成。集成大部分第三方库对象,无需配置就能使用。例如在 Spring Boot 项目中使用 MyBatis。可以直接使用 XXXMapper 对象,调用方法执行 sql 语句。

约定优于配置: Spring Boot 定义了常用类,包的位置和结构,默认的设置。代码不需要做调整,项目能够按照预期运行。比如启动类在根包的路径下,使用了@SpringBooApplication 注解。创建了默认的测试类。controller, service,dao 应该放在根包的子包中。application 为默认的配置文件。

脚手架(spring 提供的一个 web 应用,帮助开发人员,创建 springboot 项目)

SpringBoot3 最小 jdk17,支持 17-20.

Spring Boot 理念“约定优于配置”,也可称为按约定编程。

1.1 与 Spring 关系  

Spring 框架:
Spring Boot 创建的是 Spring 应用,对于这点非常重要。也就是使用 Spring 框架创建的应用程序。这里的 Spring 是指 Spring Framework。我们常说的 Spring,一般指 Spring 家族,包括 Spring Boot、Spring Framework 、Spring Data ,Spring Security,Spring Batch , Spring Shell, Spring for Apache Kafka …。

2004 年 3 月,Spring Framework1.0 发布。2006 年 10 月,Spring Framework2.0 发布。 2006 年后开始,国内项目渐渐的开始应用 Spring 框架,2009 年 12 月,Spring3.0 发布。这时国内已经比较注重 Spring 使用了。项目多数转移到 Spring 框架了。我是在 2007 开始知道渐渐了解 Spring 框架。那个时候用 Struts 或者就是 jsp+servlet+jdbc 比较多。当时研发项目也没什么烦恼,就一,两个技术可以用。没什么可选择的。现在的框架,技术太多了。2017 年 09 月,Spring Framework5.0 发布。 2022 年 11 月 Spring Framework6.0 发布。

第一个版本 1.0 的 blog: https://spring.io/blog/2004/03/24/spring-framework-1-0-final-released Spring 的核心功能:IoC , AOP , 事务管理,JDBC,SpringMVC,Spring WebFlux,集成第三方框架 MyBatis,Hibernate,Kafka,消息队列…

Spring 包含 SpringMVC, SpringMVC 作为 web 开发的强有力框架,是 Spring 中的一个模块。

首先明确一点,Spring Boot 和 Spring Framework 都是创建的 Spring 应用程序。Spring Boot 是一个新的框架,看做是 Spring 框架的扩展,它消除了设置 Spring 应用程序所需的 XML 配置,为更快,更高效的创建 Spring 应用提供了基础平台。Spring Boot 能够快速创建基于 Spring ,SpringMVC 的普通应用以及 Web 项目。

SpringBoot 是包含了 Spring 、SpringMVC 的高级的框架,提供了自动功能,短平快。能够更快的创建 Spring 应用。消除了 Spring 的 XML 配置文件,提供了开发效率,消除 Spring 应用的臃肿。避免了大量的样板代码。

所以学习 Spring Boot 的建议:了解 Spring + SpringMVC 核心功能,基本应用是最好的,能够更快的上手 Spring Boot。一般的 Spring Boot 课程中默认听众是会 Spring ,SpringMVC 的。

500

Spring Boot 在现在 Java 开发人员必须掌握的框架。Spring Boot 是掌握 Spring Cloud 的基础。

1.2 与 SpringCloud 关系

微服务: 微服务(Microservices Architecture)是一种架构和组织方法,微服务是指单个小型的但有业务功能的服务,每个服务都有自己的处理和轻量通讯机制,可以部署在单个或多个服务器上。

将一个大型应用的功能,依据业务功能类型,抽象出相对独立的功能,称为服务。每个服务就上一个应用程序,有自己的业务功能,通过轻量级的通信机制与其他服务通信(通常是基于 HTTP 的 RESTful API),协调其他服务完成业务请求的处理。这样的服务是独立的,与其他服务是隔离的,可以独立部署,运行。与其他服务解耦合。

微服务看做是模块化的应用,将一个大型应用,分成多个独立的服务,通过 http 或 rpc 将多个部分联系起来。请求沿着一定的请求路径,完成服务处理。

500

项目规模大,服务多。要构建大型的分布式应用,保证应用的稳定,高效,不间断的提供服务。Spring Cloud 是对分布式项目提供了,有力的支持。

Spring Cloud 是一系列框架的有序的组合,为开发人员提供了快速构建分布式系统中常用工具(例如,配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态)。开发人员使用使用 Spring Cloud 这套框架和工具的集合可以快速建立实现分布式服务。这些框架需要使用 Spring Boot 作为基础开发平台。

学好了 Spring Boot,才能使用这些框架,创建良好的 Spring Cloud 应用。分布式应用。

访问: https://spring.io/projects/spring-cloud

Spring Cloud 包含的这些框架和工具各负其职,例如 Spring Cloud Config 提供配置中心的能力,给分布式多个服务提供动态的数据配置,像数据库的 url,用户名和密码等,第三方接口数据等。 Spring Cloud Gateway 网关,提供服务统一入口,鉴权,路由等功能。

学习 Spring Colud 难度比较大,里面框架,工具比较多。有多个框架需要学习,在把框架组合起来又是一个难度。

1.3 最新的 Spring Boot3 新特性

2022 年 11 月 24 日。Spring Boot3 发布,里程碑的重大发布。这个版本应该是未来 5 年的使用主力。Spring 官网支持 Spring Boot3.0.X 版本到 2025 年。

SpringBoot3 中的重大变化:

  1. JDK 最小 Java 17,能够支持 17-20.
  2. Spring Boot 3.0 已将所有底层依赖项从 Java EE 迁移到了 Jakarta EE API。原来 javax 开头的包名,修改为 jakarta。例如 jakarta.servlet.http.HttpServlet 原来 javax.servlet.http.HttpServlet
  3. 支持 GraalVM 原生镜像。将 Java 应用编译为本机代码,提供显著的内存和启动性能改进。
  4. 对第三方库,更新了版本支持。
  5. 自动配置文件的修改。
  6. 提供新的声明式 Http 服务,在接口方法上声明 @HttpExchange 获取 http 远程访问的能力。代替 OpenFeign
  7. Spring HTTP 客户端提供基于 Micrometer 的可观察性. 跟踪服务,记录服务运行状态等
  8. AOT(预先编译) 支持 Ahead Of Time,指运行前编译
  9. Servlet6.0 规范
  10. 支持 Jackson 2.14。
  11. Spring MVC: 默认情况下使用的 PathPatternParser。删除过时的文件和 FreeMarker、JSP 支持。

伴随着 Spring Boot3 的发布,还有 Spring Framework 6.0 的发布(2022-11-16),先于 Spring Boot 发布。

1.4 如何学好框架

学习框架: 我的建议无基础,先看视频,照着例子做;有基础后自己做点程序。之后看图书,最好是官网文档。不建议开始就看源代码。

有基础的:看图书,最好是官网文档,边看文档边实践。可以看框架此处功能的源代码。不建议通篇看源代码(在巨人身上是看不到全貌的)。提高部分看开源项目的代码,最后写项目。

2 脚手架  

脚手架是一种用在建筑领域的辅助工具,是为了保证建筑施工过程顺利进行而搭设的工作平台。软件工程中的脚手架是用来快速搭建一个小的可用的应用程序的骨架,将开发过程中要用到的工具、环境都配置好,同时生成必要的模板代码。

脚手架辅助创建程序的工具,Spring Initializr 是创建 Spring Boot 项目的脚手架。快速建立 Spring Boot 项目的最好方式。他是一个 web 应用,能够在浏览器中使用。IDEA 中继承了此工具,用来快速创建 Spring Boot 项目以及 Spring Cloud 项目。

Spring Initializr 脚手架的 web 地址: https://start.spring.io/

阿里云脚手架: https://start.aliyun.com/

2.1 使用脚手架创建项目

  1. 浏览器访问脚手架,创建项目
  2. IDEA 中使用脚手架。

脚手架使用需要联网。

2.2 IDEA 创建 SpringBoot 项目  

3 代码结构  

3.1 单一模块

一个工程一个模块的完整功实现。

+----Application.java 启动类              
+----controller  控制器包                      
	---StudentController.java                      
	---ScoreController.java                
+----service 业务层包                      
	--inter 业务层接口                      
	---impl 接口实现包                
+----repository 持久层包                
+----model 模型包                      
	---entity 实体类包                      
	---dto 数据传输包                          
	---vo 视图数据包 

3.2 多个模块

一个 Spring Boot 中多个模块。在根包下创建每个模块的子包,子包中可以按“单一模块”包结构定义。创建包含多个功能的单体 Spring Boot。

+----Application.java 启动类  
+----activity 活动模块
	---上述的单一模块架构
+----sale 售卖模块
	---上述的单一模块架构 
+----user 用户模块
	---上述的单一模块架构

3.3 包和主类  

我们通常建议您将主应用程序类定位在其他类之上的根包中。@SpringBootApplication 注释通常放在主类上,它隐式地为某些项定义了一个基本的“搜索包”。例如,如果您正在编写一个 JPA 应用程序,则使用@SpringBootApplication 注释类的包来搜索@Entity 项。使用根包还允许组件扫描只应用于您的项目。

Spring Boot 支持基于 java 的配置。尽管可以将 SpringApplication 与 XML 源一起使用,但我们通常建议您的主源是单个 @Configuration 类。通常,定义主方法的类可以作为主 @Configuration 类。

3.4 spring-boot-starter-parent

pom.xml 中的 <parent> 指定 spring-boot-starter-parent 作为坐标,表示继承 Spring Boot 提供的父项目。从 spring-boot-starter-parent 继承以获得合理的默认值和完整的依赖树,以便快速建立一个 Spring Boot 项目。父项目提供以下功能:

  • JDK 的基准版本,比如 <java.version>17</java.version>
  • 源码使用 UTF-8 格式编码
  • 公共依赖的版本
  • 自动化的资源过滤:默认把 src/main/resources 目录下的文件进行资源打包
  • maven 的占位符为‘@’
  • 对多个 Maven 插件做了默认配置,如 maven-compile-plugin,maven-jar-plugin

如果不通过 SpringBoot 创建器创建,想要快速创建 Spring Boot 项目,同时能够使用父项目带来的便利性,可以采用如下两种方式:

  1. 在项目中,继承 spring-boot-starter-parent
  2. pom.xml 不继承,单独加入 spring-boot-dependencies 依赖。
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-dependencies</artifactId>
			<version>3.0.1</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

4 SpringBoot 核心注解 TODO

039-Core-核心注解_哔哩哔哩_bilibili

5 运行 Spring Boot 项目方式

Spring Boot 项目可以打包为 jar 或者 war 文件。因为 Spring Boot 内嵌了 web 服务器,例如 tomcat。能够以 jar 方式运行 web 应用。无需安装 tomcat 程序。

三种启动方式:

  • 开发工具,例如 IDEA 执行 main 方法

  • Maven 插件 mvn spring-boot:run 
    500

  • java -jar jar 文件的路径(适合部署到服务器中进行开发)

    <build>
    	<!-- myWeb.jar -->
    	<finalName>myWeb</finalName>
    	<plugins>
    		...
    	</plugins>
    </build>

    maven clean & package 生成 jar 包,命令行运行 java -jar jar myWeb.jar 就可以启动项目了。

普通的 jar 与 Spring Boot jar 区别:

项目spring boot jar普通的 jar
目录BOOT-INF : 应用的 class 和依赖 jar
META-INF: 清单
org.springframework.boot.loader: spring-boot-loader 模块类
META-INF:清单
class 的文件夹:jar 中的所有类
BOOT-INFclass:应用的类
lib:应用的依赖
没有 BOOT-INF
spring-boot-loader执行 jar 的 spring boot 类没有此部分
可执行

命令:powershell 中 tree  /F

Spring Boot jar 文件的结构:

500

6 starter

starter 是一组依赖描述,应用中包含 starter,可以获取 spring 相关技术的一站式的依赖和版本。不必复制、粘粘代码。通过 starter 能够快速启动并运行项目。

starter 包含:

  • 依赖坐标、版本
  • 传递依赖的坐标、版本
  • 配置类,配置项

pom.xml 加入 mybatis 依赖

<dependency>  
	<groupId>org.mybatis.spring.boot</groupId>  
	<artifactId>mybatis-spring-boot-starter</artifactId>  
	<version>2.2.2</version>
</dependency

查看 Maven 依赖
500

MyBatis 配置类

500

7 外部化配置

外部化配置应用程序 =   代码  + 数据(数据库,文件,url)

应用程序的配置文件:Spring Boot 允许在代码之外,提供应用程序运行的数据,以便在不同的环境中使用相同的应用程序代码。避免硬编码,提供系统的灵活性。可使用各种外部配置源,包括 Java 属性文件、YAML 文件、环境变量和命令行参数。

项目中经常使用 properties 与 yaml 文件,其次是命令行参数。

7.1 配置文件基础  

7.1.1 配置文件格式  

配置文件有两种格式分别:properies 和 yaml(yml)。properties 是 Java 中的常用的一种配置文件格式,key=value。key 是唯一的,文件扩展名为 properties。

yaml(YAML Ain’t Markup Language)也看做是 yml,是一种做配置文件的数据格式,基本的语法 key:[空格]值。yml 文件文件扩展名是 yaml 或 yml(常用)。

YAML 基本语法规则:

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进只可以使用空格,不允许使用 Tab 键
  • 缩进的空格数目不重要,相同层级的元素左侧对齐即可
  • # 字符表示注释,只支持单行注释。# 放在注释行的第一个字符

YAML 缩进必须使用空格,而且区分大小写,建议编写 YAML 文件只用小写和空格。

YAML 支持三种数据结构

  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
  • 标量(scalars):单个的、不可再分的值,例如数字、字符串、true | false 等

需要掌握数据结构完整内容,可从 https://yaml.org/type/index.html 获取详细介绍。

7.1.2 application 文件  

Spring Boot 同时支持 properties 和 yml 格式的配置文件。配置文件名称默认是 application。我们可以使用 application.properties , application.yml。

读取配置文件的 key 值,注入到 Bean 的属性可用 @Value,@Value 一次注入一个 key 的值。将多个 key 值绑定到 Bean 的多个属性要用到 @ConfigurationProperties 注解。在代码中访问属性除了注解,Spring 提供了外部化配置的抽象对象 Environment。Environment 包含了几乎所有外部配置文件,环境变量,命令行参数等的所有 key 和 value。需要使用 Environment 的注入此对象,调用它的 getProperty(String key)方法即可。

Spring Boot 建议使用一种格式的配置文件,如果 properties 和 yml 都存在。properties 文件优先。推荐使用 yml 文件。 application 配置文件的名称和位置都可以修改。约定名称为 application,位置为 resources 目录。

7.1.3 application.properties

600

7.1.4 application.yml (推荐)

600

7.1.5 Environment 

Environment 是外部化的抽象,是多种数据来源的集合,存在于容器中。

Environment 包含了 application 配置文件,环境变量,系统属性。

当在 Bean 中注入 Environment 后,就可以调用该对象的 getProperty(key)方法来获取属性值。

step1:创建 ReadConfig 类,注入 Environment

@Service
public class ReadConfig {
	@Autowired
	private Environment environment;
 
	public void print(){
		String name = environment.getProperty("app.name");
		//key 是否存在
		if (environment.containsProperty("app.owner")) {
			System.out.println("有 app.owner 配置项");
		}
		//读取 key 转为需要的类型,提供默认值 8000
		Integer port = environment.getProperty("app.port", Integer.class, 8000);
		String result = String.format("读取的 name:%s,端口 port:%d", name,port);
		System.out.println("result = " + result);
	}
}

step2:单元测试

@SpringBootTest
class ReadConfigTest {
	@Autowired
	private ReadConfig readConfig;
 
	@Test
	void test01() {
	readConfig.print();
	}
}

输出:

有 app.owner 配置项
result = 读取的 name:Lession07-yml,端口 port:8002

7.1.6 组织多文件  

当配置内容较多时,可以配置多个文件,最后集中到 application 文件中。

step1:在 resources 创建自定义 conf 目录,在 conf 中创建 redis.yml, db.yml

700

step2: application.yml 导入多个配置

500

step3:创建类,读取两个文件的配置项

@Service
public class MultiConfigService {
 
  @Value("${spring.redis.host}")
  private String redisHost;
 
  @Value("${spring.datasource.url}")
  private String dbUrl;
 
  public void printConfig(){
    System.out.println("redis的ip:"+redisHost+",数据库url;"+dbUrl);
 }
}

7.1.7 多环境配置

软件开发中经常提到环境这个概念,与日常生活中的环境概念一样。环境影响居住体验。影响软件运行的也叫做环境,例如应用中访问数据库的 ip,用户名和密码,Redis 的端口,配置文件的路径,windows,linux 系统,tomcat 服务器等等。围绕着程序周围的都是环境。环境影响软件的运行。

Spring Profiles 表示环境,Profiles 有助于隔离应用程序配置,并使它们仅在某些环境中可用。常说开发环境,测试环境,生产环境等等。一个环境就是一组相关的配置数据,支撑我们的应用在这些配置下运行。应用启动时指定适合的环境。开发环境下每个开发人员使用自己的数据库 ip,用户,redis 端口。同一个程序现在要测试了。需要把数据库 ip,redis 的改变为测试服务器上的信息。此时使用多环境能够方便解决这个问题。

Spring Boot 规定环境文件的名称 application-{profile}.properties(yml)。其中 profile 为自定义的环境名称,推荐使用 dev 表示开发,test 表示测试。 prod 表示生产,feature 表示特性。总是 profile 名称是自定义的。Spring Boot 会加载 application 以及 application-{profile}两类文件,不是只单独加载 application-{profile}。

需求: 项目使用多环境配置,准备一个开发环境,一个测试环境.。

step1:在 resources 创建环境配置文件

600

step2: 激活环境

spring:
  config:
	#导入多个配置文件,“,”作为分隔符
    import: conf/db.yml,conf/redis.yml
	#激活环境,与on-profile名称保持一致
  profiles:
    active: dev

step3: 创建读取配置项的类

@Service
public class MulitEnvService {
  @Value("${myapp.memo}")
  private String memo;
  public void print(){
    System.out.println(memo);
  }
}

7.2 绑定 Bean

@Value 绑定单个属性,当属性较多时不方便,Spring Boot 提供了另一种属性的方法。将多个配置项绑定到 Bean 的属性,提供强类型的 Bean。Bean 能够访问到配置数据。

基本原则:标准的 Java Bean 有无参数构造方法,包含属性的访问器。配合 @ConfigurationProperties 注解一起使用。Bean 的 static 属性不支持。

Spring Boot 自动配置中大量使用了绑定 Bean 与 @ConfigurationProperties,提供对框架的定制参数。项目中要使用的数据如果是可变的,推荐在 yml 或 properties 中提供。项目代码具有较大的灵活性。

@ConfigurationProperties 能够配置多个简单类型属性,同时支持 Map,List,数组类型。对属性还能验证基本格式。

7.2.1 简单的属性绑定  

使用之前的 app 开头的配置内容。yml,properties 配置格式都可以,绑定 Bean 的效果都一样。 step1:查看 application 配置。目前使用的是 application.yml

400

step2: 创建 Bean,定义 name,owner, port 属性

@Component
@ConfigurationProperties(prefix = "app")
public class AppBean {
  private String name;
  private String owner;
  private Integer port;
 // set | get方法 ,toString()
}
 
// proxyBeanMethods = false
// 创建普通 Bean,对这个 Bean 不进行代理,创建更快
@Configuration(proxyBeanMethods = false)
@ConfigurationProperties(prefix = "app")
public class AppBean {
  private String name;
  private String owner;
  private Integer port;
 // set | get方法 ,toString()
}

@ConfigurationProperties 声明在类上,表示绑定属性到此类。prefix 表示前缀,是配置文件中多个 key 的公共前缀。这些 key 以“.”作为分隔符。例如 app.name, app: name 等。 prefix=”app”, 将文件中 app 开始的 key 都找到,调用与 key 相同名称的 setXXX 方法。如果有给属性赋值成功。没有的忽略。

7.2.2 嵌套 Bean 

需求:Bean 中包含其他 Bean 作为属性,将配置文件中的配置项绑定到 Bean 以及引用类型的成员。Bean 的定义无特殊要求。

在原来的 app 的配置中,增加 security 相关配置,包含 username,password 两个属性。

step1: 定义两个 Bean

public class Security {
  private String username;
 private String password;
  // set | get方法 ,toString()
}
 
@Configuration(proxyBeanMethods = false)
@ConfigurationProperties(prefix = "app")
public class NestAppBean {
  private String name;
  private String owner;
  private Integer port;
  private Security security;
  // set | get方法 ,toString()
}

step2: 定义 application.yml

app:
  name: Lession07-yml
  owner: bjpowernode
  port: 8002
  security:
    username: root
    password: 123456

7.2.3 扫描注解  

@ConfigurationProperties 注解起作用,还需要 @EnableConfigurationProperties 或@ConfigurationPropertiesScan。这个注解是专门寻找 @ConfigurationProperties 注解的,将他的对象注入到 Spring 容器。在启动类上使用扫描注解。

// @EnableConfigurationProperties(NestAppBean.class)
// 使用 @EnableConfigurationProperties 注解后,就不需要 @Configuration 注解了
// @ConfigurationPropertiesScan 注解同样
// 不过这些注解不扫描 @Component 注解
@ConfigurationPropertiesScan({"com.bjpowernode.config.pk4"})
@SpringBootApplication
public class Lession07ConfigApplication {
 
  public static void main(String[] args) {
    SpringApplication.run(Lession07ConfigApplication.class, args);
  }
}

7.2.4 处理第三方库对象

上面的例子都是在源代码中使用 @ConfigurationProperties 注解,如果某个类需要在配置文件中提供数据,但是没有源代码。此时 @ConfigurationProperties 结合 @Bean 一起在方法上面使用。

比如现在有一个 Security 类是第三方库中的类,现在要提供它的 username,password 属性值。

step1: application.yml 添加新的配置

security:
  username: common
  password: abc123

step2:创建配置类

@Configuration
public class ApplicationConfig {
 
  @ConfigurationProperties(prefix = "security")
  @Bean
  public Security createSecurity(){
    return new Security();
  }
}

7.2.5 Map、List、Array 

Map,List 以及 Array 都能提供配置数据,下面通过一个示例配置集合属性。

step1:创建保存数据的 Bean

public class User {
  private String name;
  private String sex;
  private Integer age;
  //set | get ,toString
}
 
public class MyServer {
  private String title;
  private String ip;
  //set | get ,toString
}
 
@ConfigurationProperties
public class CollectionConfig {
 
  private List<MyServer> servers;
  private Map<String,User> users;
  private String [] names;
  //set | get ,toString
}

step2: 修改 application.yml, 配置数据

#集合以及数组
#List<String> names
names:
  - lisi
  - zhangsan
 
#List<MyServer> servers
servers:
  - title: 华北服务器
    ip: 202.12.39.1
  - title: 西南服务器
    ip: 106.90.23.229  - title: 南方服务器
    ip: 100.21.56.23
 
#Map<String,User> users
users:
  user1:
      name: 张三
      sex: 
      age: 22
  user2:
      name: 李四
      sex: 
      age: 26

“-”表示集合一个成员,因为成员是对象,需要属性名称指定属性值。List 与数组前面加入“-”表示一个成员。 Map 直接指定 key 和 value,无需“-”。

step3: 启动类,增加扫描包

@ConfigurationPropertiesScan({"其他包","com.bjpowernode.config.pk5"})
@SpringBootApplication
public class Lession07ConfigApplication {
 
  public static void main(String[] args) {
    SpringApplication.run(Lession07ConfigApplication.class, args);
  }
}

7.2.6 指定数据源文件  

application 做配置是经常使用的,除以以外我们能够指定某个文件作为数据来源。@PropertySource 是注解,用以加载指定的 properties 文件。也可以是 XML 文件(无需了解)。@PropertySource 与@Configuration 一同使用,其他注解还有@Value,@ConfigurationProperties。

需求:一个组织信息,在单独的 properties 文件提供组织的名称,管理者和成员数量

step1: 创建 Group 类,表示组织

@Configuration
@ConfigurationProperties(prefix = "group")
@PropertySource(value = "classpath:/group-info.properties")
public class Group {
 
 
  private String name;
 private String leader;
  private Integer members;
  //set | get ,toString
}

step2:在 resources 目录下的任意位置创建 properties 文件,我们创建 group-info.properties,放在 resources 根目录。

400

总结:

@ConfigurationProperties 绑定 Bean 对于使用配置文件的数据是十分方便,灵活的。也支持对数据的校验,校验是 JSR303 规范中的注解。

8 创建对象三种方式  

  • 将对象注入到 Spring 容器,可以通过如下方式:
  • 传统的 XML 配置文件
  • Java Config 技术, @Configuration 与 @Bean
  • 创建对象的注解,@Controller ,@Service , @Repository ,@Component

Spring Boot 不建议使用 xml 文件的方式,自动配置已经解决了大部分 xml 中的工作了。如果需要 xml 提供 bean 的声明,@ImportResource 加载 xml 注册 Bean。

需求:XML 配置 Spring 容器,声明 Bean

public class Person {
  private String name;
  private Integer age;
  //set | get ,toString
}

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="myPerson" class="com.bjpowernode.config.pk7.Person">
    <property name="name" value="李四" />
    <property name="age" value="20" />
  </bean>
</beans>

step3: 启动类,从容器中获取 Person 对象

@ImportResource(locations = "classpath:/applicationContext.xml")
@ConfigurationPropertiesScan({"com.bjpowernode.config.pk4", "com.bjpowernode.config.pk5"})
@SpringBootApplicationpublic class Lession07ConfigApplication {
 
  public static void main(String[] args) {
    ApplicationContext ctx = SpringApplication.run(Lession07ConfigApplication.class, args);
    Person myPerson = (Person) ctx.getBean("myPerson");
    System.out.println("myPerson = " + myPerson);
  }
}

9 AOP 

需求:项目中的业务方法都需要在日志中输出方法调用的时间以及参数明细。业务方法多,使用 AOP 最合适。新建 Spring Boot 项目 Lession08-aop , Maven 管理项目,无需选择依赖。包名称。com.bjpowernode.aop

step1:Maven 添加 aop 依赖,包含了 aop 和 aspectj 依赖

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

step2:创建业务类 SomeService 在 aop 的 service 子包

public interface SomeService {
  void query(Integer id);
  void save(String name, String code);
}
 
@Service
public class SomeServiceImpl implements SomeService {
 
  @Override
  public void query(Integer id) {
    System.out.println("SomeService业务方法query执行了");
  }
 
  @Override
  public void save(String name, String code) {
    System.out.println("SomeService业务方法save执行了");
  }
}

step3:创建切面类

@Component
@Aspect
public class LogAspect {
 
 
  //前置通知 execution是切入点表达式
  @Before("execution(* com.bjpowernode.aop.service..*.*(..))")
  public void sysLog(JoinPoint jp){
    StringJoiner log = new StringJoiner("|", "{", "}");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    log.add(formatter.format(LocalDateTime.now()));
    //目标方法参数列表
    Object[] args = jp.getArgs();
    for (Object arg : args) {
      log.add( arg == null ? "-" : arg.toString());
    }
    System.out.println("方法执行日志:" + log.toString());
  }
}
 

step4:单元测试

@SpringBootTest
public class AspectTest {
 
  @Autowired
  private SomeService service;
 
 
  @Test
  void testLog() {
    service.query(1001);
    service.save("订单业务", "B01256");
  }
}

输出执行结果:

方法执行日志:{2023-01-22 13:52:43|1001}
SomeService 业务方法 query 执行了
方法执行日志:{2023-01-22 13:52:43|订单业务|B01256}
SomeService 业务方法 save 执行了

结论:在业务方法前,先执行了切面类中 sysLog() 的功能增强代码。