SpringBoot学习(三)数据访问、基础特性、核心原理

数据访问

整个SSM场景:Spring、SpringMVC、MyBatis

示例

  1. 依赖
<!--ssm-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
    <scope>runtime</scope>
</dependency>
  1. 数据库配置资源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/ssm
spring.datasource.username=root
spring.datasource.password=root
  • 可用MyBatisX插件,帮助生产Mapper接口的xml文件
  1. 配置MyBatis
# 指定mapper映射文件位置
mybatis.mapper-locations=classpath:/mapper/*.xml
# 参数项调整为驼峰命名,便于匹配字段与数据项
mybatis.configuration.map-underscore-to-camel-case=true
  1. CRUD
  • 每个方法都应在Mapper文件中有一个sql标签与之对应
  • 所有参数都应用@Param进行签名,以后使用指定签名在SQL中取值
  • 使用@MapperScan(批量扫描)告知MyBatis,扫描哪个包下的所有接口
  • 使用mybatis.mapper-locations告知MyBatis,接口对应的xml文件在哪里
  • MyBatis自动关联由接口全类名等同namespace值来实现
  • sql写在xml中,mybatis配置写在application.properties

自动配置原理

jdbc场景自动配置数据源等基本信息

  1. mybatis-spring-boot-starter导入spring-boot-starter-jdbc作为操作数据的场景
  2. 默认配置类:
  • org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration:
  • 数据源的自动配置
  • 所有和数据源有关的配置都绑定在DataSourceProperties
  • 默认使用HikariDataSource
  • org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
  • 向容器中放置了JdbcTemplate以操作数据库
  • org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration
  • org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration:
  • 基于XA二阶提交协议的分布式事务数据源
  • org.springframework.boot.autoconfigure.jdbc.DataSourceTransacitonManagerAutoConfiguration:
  • 支持事务
  1. 底层能力:数据源、JdbcTemplate、事务

MyBatisAutoConfiguration配置MyBatis整合流程

  1. mybatis-spring-boot-starter导入mybatis-spring-boot-autoconfigure(mybatis的自动配置包)
  2. 默认配置类:
  • org.springframework.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration
  • org.springframework.boot.autoconfigure.MybatisAutoConfiguration:
  • 必须在数据源配置成功后才进行配置
  • 向容器中放置SqlSessionFactory组件,创建和数据库的一次会话
  • 向容器中放置SqlSessionTemplate组件,操作数据库
  1. MyBatis的所有配置绑定在MyBatisProperties
  2. 利用@MapperScan原理,将Mapper接口的代理对象创建并放入容器:
  • 利用@Import(MapperScannerRegister.class)批量向容器中注册组件,解析指定包路径中的所有类,为所有Mapper接口类创建Bean信息,并注册到容器中

基础特性

SpringApplication

自定义banner

  1. 类路径添加banner.txt或设置spring.banner.location可以设置banner样式
  2. spring.main.banner-mode=off可以快速关闭banner

自定义SpringApplication

@SpringBootApplication
public class MyApplication {
	public static void main(string[] args) {
		SpringApplication application = new SpringApplication(MyApplication.class);
		application.setBannerMode(Banner.Mode.OFF);
		application.run(args);
	}
}

FluentBuilder API

new SpringApplicationBuilder()
	.sources(Parent.class)
	.child(Application.class)
	.bannerMode(Banner.Mode.OFF)
	.run(args);

Profiles

期待快速切换开发、测试、生产环境的环境隔离能力:

  1. 标识环境:指定对应组件、配置在对应位置生效
  2. 切换环境:使用特定环境时,对应的所有组件和配置则生效

使用

指定环境
  1. Spring Profiles提供一种隔离配置的方式,使其仅在特定环境下生效
  2. 任何@Component@Configuration@ConfigurationProperties都可以使用@Profile进行标记,指定何时被加载
@Profile({"test"})
  1. 不被@Profile标记的组件代表任意时刻都生效,不区分环境
环境激活
  1. 配置激活环境
spring.profiles.active=production,hsqldb
or
spring.profiles.active[0]=production
spring.profiles.active[1]=hsqldb
  1. 命令行激活
java -jar xxx.jar --spring.profile.active=development,hsqldb
  1. 配置默认环境,未指明时使用该环境对应组件和配置(推荐使用激活方式选择场景,而非指定默认方式固定使用某个场景)
spring.profiles.default=test
环境包含
  1. 包含场景:无论在何种情况下都会生效的场景
spring.profiles.include=test, development
  1. spring.profiles.activespring.profiles.default只能用到无profile的文件中,若在application-test.yaml中编写则是无效指令
  2. 可以额外添加生效文件,而非激活替换
spring.profiles.include[0]=common
spring.profiles.include[1]=local
  1. 最终生效的场景 = 激活/默认场景 + 包含场景
  2. 在项目中:
  • 基础的配置mybatislogxxx等写入包含场景
  • 动态切换变化的配置dbredis等写入激活/默认场景

Profiles配置文件

  1. application.properties主配置文件,任何情况下生效
  2. 命名规范:application-{profile标识}.properties
  3. 激活指定场景使用,项目生效配置 = 激活场景配置文件的所有项 + 主配置文件和激活文件不冲突的所有项(冲突项以激活场景配置文件为准)

外部化配置

线上应用快速修改配置,至最新配置

  • SpringBoot使用 配置优先级+外部配置 简化配置更新、简化运维
  • 给jar应用所在文件夹放置application.properties最新配置文件,重启项目即可自动应用最新配置

配置优先级

SpringBoot允许将配置外部化,以便在不同环境中使用相同的应用程序代码

  1. 对SpringBoot属性源的加载顺序,优先级顺序为(数字与优先级相反):
优先级属性原
14默认属性(通过SpringApplication.setDefaultProperties指定)
13@PropertySource指定加载配置(需写在@Configuration类上)
12配置文件(`application.properties/yml等)
11RandomValuePropertySource支持的random.*配置(eg.`@Value("$(random.int)*))
10OS环境变量
9Java系统属性(System.getProperties()
8JNDI属性(来自java:comp/env
7ServletContext初始化参数
6ServletConfig初始化参数
5SPRING_APPLICATION_JSON属性(内置在环境变量或系统属性中的JSON)
4命令行参数
3测试属性(@SpringBootTest测试时指定的属性)
2测试类@TestPropertySource注解
1Devtools设置的全局属性($HOME/.config/spring-boot
  1. 常用
  • 命令行 > 配置文件 > springapplication配置
  • 配置文件的优先级:
  • 包外 > 包内;
  • profile > application
  • .properties > .yml
  • config目录 > 根目录

外部配置

在这里插入图片描述

导入配置

#导入额外配置,值总是优先于文件内部编写的值
spring.boot.import=classpath:/*.properties

属性占位符

#去除曾配置过的项的值
#Unknown代表默认值,选填
app.name=MyApp
app.description={$name:dault} is a Spring Boot application written by ${username:Unknown)

单元测试-JUnit5

整合

SpringBoot存在一系列测试工具及注解方便用户调用测试
spring-boot-test提供核心测试能力、spring-boot-test-autoconfigure提供部分测试配置

<!--test单元测试-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

测试

组件测试,直接使用@Autowired容器组件注入

注解
注解用法
@Test标识为测试方法,但不同于Junit4的同名注解,该注解不能声明任何属性,拓展测试将由Jupiter提供额外测试进行
@Parameterized标识参数化测试方法
@Repeated标识可重复执行方法
@DisplayName为测试类或测试方法设置展示名
@BeforeEach表示在每个单元测试前执行
@AfterEach表示在每个单元测试后执行
@BeforeAll表示在所有单元测试前执行
@AfterAll表示在所有单元测试后执行
@Tag标识单元测试类型,类似于Junit4的@Categories
@Disabled标识不执行该测试类或测试方法,类似于Junit4的@Ignore
@Timeout标识测试方法最大运行时间及超时会返回错误
@ExtendWith测试类或测试方法拓展类引用
断言
方法说明
assertEquals判断两个对象或两个原始类型是否相等
assertNotEquals判断两个对象或两个原始类型是否不相等
assertSame判断两个对象引用是否值相同对象
assertNotSame判断两个对象引用是否值不同对象
asserTrue判断给定布尔值是否为true
asserFalse判断给定布尔值是否为false
asserNull判断给定对象引用是否为null
asserNotNull判断给定对象引用是否不为null
assertArrayEquals数组断言
assertAll组合断言
assertThrows异常断言
assertTimeout超时断言
fall快速失败

核心原理

事件和监听器

生命周期监听

监听应用的生命周期

监听器
  1. 自定义SpringApplicationRunListener来监听事件:
  • 编写SpringApplicationRunListener实现类
  • META-INF/spring.factories中配置org.springframework.boot.SpringApplicationRunListener=个人Listener,还可指定一个有参构造器,接受参数(SpringApplication application, String[] args)
  • SpringBoot在spring-boot.jar中配置了默认Listener:
  • org.springframework.boot.SpringApplicationRunListener=\
  • org.springframework.boot.context.event.EventPublishingRunListener
  1. 引导:利用 BootstrapContext 引导整个项目启动
  • starting:应用开始,SpringApplicationrun 方法调用,只要存在 BootstrapContext 就执行
  • environmentPrepared:环境准备完毕(将启动参数等绑定到环境变量中),但IoC还未创建
  1. 启动:
  • contextPrepared:IiC容器创建且准备完毕,但主配置类sources未加载,关闭引导启动器
  • contextLoaded:IoC容器与主配置类加载完毕,但IoC容器还未刷新(Bean还未创建)
  • started:IoC容器刷新(Bean准备完毕),但runner未调用
  • ready:IoC容器刷新(Bean准备完毕),runner调用完毕
  1. 运行:步骤正确执行后,容器开始running
生命周期全流程

在这里插入图片描述

事件触发时机

各种回调监听器
  1. BootstrapRegistryInitializer:感知遇到初始化阶段
  • META-INF/spring.factories
  • 创建引导上下文bootstrapContext的时候触发
  • 场景:进行密钥校对授权
  1. ApplicationContextInitializer:感知IoC容器初始化阶段
  • META-INFO/spring.factories
  1. ApplicationListener:感知全阶段,基于事件机制感知事件,处于某个阶段允许执行对应操作
  • @Bean@EventListener:事件驱动
  • SpringApplication.addListeners()SpringApplicationBuilder.listeners()
  • META-INF/spring.factories
  1. SpringApplicationRunListener:感知全阶段,在任意阶段都能够自定义操作,更加完善的功能覆盖面
  • META-INF/spring.factories
  1. ApplicationRunner:感知特定阶段,感知到应用就绪时Ready;感知到应用卡死,不进入就绪
  • @Bean
  1. CommandLineRunner:感知特定阶段,感知到应用就绪时Ready;感知到应用卡死,不进入就绪
  • @Bean
  • 示例:
  • 若项目启动前操作:BootstrapRegistryInitializerApplicationContextInitializer
  • 若项目启动后操作:ApplicationRunnerCommandLineRunner
  • 若要干涉生命周期操作:SpringApplicationRunListener
  • 若要使用事件机制:ApplicationListener
完整触发流程
事件触发时机
ApplicationStartingEvent应用启动但未做任何操作,越过注册listeners and initializers
ApplicationEnvironmentPreparedEvent环境准备好,但context未创建
ApplicationContextInitializedEventApplicationContext准备好,ApplicationContextInitializers调用,单位加载任何Bean
ApplicationPreparedEvent容器刷新之前,Bean定义信息加载
ApplicationStartedEvent容器刷新完成,runner未调用
AvailabilityChangeEventLivenessState.CORRECT应用存活—存活探针
ApplicationReadyEvent任何runner被调用
AvailabilityChangeEventReadinessState.ACCEPTING_TRAFFIC接收请求—就绪探针
ApplicationFailedEvent启动出错

在这里插入图片描述

SpringBoot事件驱动开发

应用启动过程生命周期事件感知(9种给定情况)、应用运行中事件感知(无数种自定义)

  • 事件发布:ApplicationEventPublishAware或注入ApplicationEventMulticaster
  • 事件监听:组件 + @EventListener
    在这里插入图片描述

自动配置原理

入门

应用关注核心:场景、配置、组件

自动配置流程
  1. 导入starter
  2. 导入依赖autoconfigure
  3. 寻找类路径META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
  4. 加载所有自动配置类*AutoConfiguration
  • 给容器中配置功能组件
  • 组件参数绑定到属性类中*Properties
  • 属性类和配置文件前缀绑定
  • @Conditional派生条件注解判定组件是否生效
  1. 效果:
  • 修改配置文件、底层参数
  • 所有场景自动配置直接使用
  • 可注入SpringBoot准备好的组件直接使用
SPI机制
  1. SPI(Service Provider Interface)是一种软件设计模式,用于在应用程序中动态发现和加载组件
  2. SPI思想定义一个接口或抽象类,再通过classpath中定义好的实现该接口的类,解决对组件的动态发现和加载
  3. Java中SPI由META-INF/services目录下创建一个以服务接口全限定名为名的文件,其中包含实现该服务接口的类的全限定名,Java SPI会自动扫描classpath并根据文件中指定的类名来加载实现类
  4. SPI机制使得程序更加灵活、可扩展,同时增加代码可维护性和避免硬编码依赖关系
功能开关
  1. 自动配置:自动化,项目启动时spi文件指定的所有内容都加载
  2. @Enable*:手动控制开启*功能,利用@Import将需要的功能单独导入

进阶

@SpringBootApplication
  1. @SpringBootConfiguration:就是@Configuration,容器中的组件、配置类,spring IoC启动即创建该类对象
  2. @EnableAutoConfiguration:开启自动配置
  3. @AutoConfigurationPackage:扫描主程序包:加载自身的组件
  • 利用@Import(AutoConfigurationPackages.Registrar.class)给容器中导入需要的组件
  • 把主程序所在的包的所有组件都导入进来
  1. @Import(AutoConfigurationImportSelector.class):加载所有自动配置类:starter导入的组件
  2. @ComponentScan:组件扫描,排除已扫描进来的非必要配置类和自动配置类
完整启动加载流程

在这里插入图片描述

自定义starter

  1. 创建自定义starter项目,引入spring-boot-starter依赖
  2. 编写模块功能,并引入模块所需依赖,编写*AutoConfiguration自动配置类
  3. 编写配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,指定启动时需要加载的自动配置
  4. 等待其他项目引入

业务代码

自定义配置显示提示:导入依赖并重启项目,再次填写配置文件时跳出补完提示

<!--导入配置处理器,使配置文件properties配置显示补完提示-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-configuration-processor</artifactId>
   <optional>true</optional>
</dependency>
@ConfigurationProperties(prefix="robot")//此属性类和配置文件指定前缀绑定
@Component
@Data
public class RobotProperties {
	private String name;
	private String emial;
}

基本抽取

  1. 创建starter项目,把公共代码需要的所有依赖导入
  2. 复制公共代码
  3. 自定义一个RobotAutoConfiguration,向容器中放置该场景所需的所有组件(因为starter所在的包和引入它的项目的主程序所在的包并非父子层级,所有这些组件不会被默认扫描到)
  4. 其他用户引用该starter时,直接导入这个RobotAutoConfiguration,就能将该场景的组件导入

使用Enable机制

其他用户引用该starter时,使用@EnableRobot开启对应功能

@Retention(RetentionPolicy.RUNTIME)
@Target({ElemenType.TYPE})
@Documented
@Import(RobotAutoConfiguration.class)
public @interface EnableRobot {...}

完全自动

依赖SpringBoot的SPI机制

  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中编写好自定义的自动配置类的全类名
  • 项目启动时,自动加载声明的自动配置类
  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值