SpringBoot
SpringBoot
1、概述
SpringBoot 概念
SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻
辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度
上缩短了项目周期。2014 年 4 月,Spring Boot 1.0.0 发布。Spring的顶级项目之一(https://spring.io)。
Spring 缺点
1) 配置繁琐
虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。一开始,Spring用XML配置,而且是很多
XML配置。Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式XML配置。
Spring 3.0引入了基于Java的配置,这是一种类型安全的可重构配置方式,可以代替XML。
所有这些配置都代表了开发时的损耗。因为在思考Spring特性配置和解决业务问题之间需要进行思维切换,所
以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring实用,但它要求的回报也不少。
2)依赖繁琐
项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导
入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发
进度。
SpringBoot 功能
1) 自动配置
Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定
Spring配置应该用哪个,不该用哪个。该过程是SpringBoot自动完成的。
2) 起步依赖
起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖
,这些东西加在一起即支持某项功能。
简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
3) 辅助功能
提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
Spring Boot 并不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式。
小结
SpringBoot提供了一种快速开发Spring项目的方式,而不是对Spring功能上的增强。
Spring的缺点:
- 配置繁琐
- 依赖繁琐
SpringBoot功能:
- 自动配置
- 起步依赖:依赖传递
- 辅助功能
2、SpringBoot 快速入门
http://c.biancheng.net/spring_boot
案例:需求
搭建SpringBoot工程,定义HelloController.hello()方法,返回”Hello SpringBoot!”。
案例:实现步骤
① 创建Maven项目
② 导入SpringBoot起步依赖
③ 定义Controller
④ 编写引导类
⑤ 启动测试
小结:
- SpringBoot在创建项目时,使用jar的打包方式。
- SpringBoot的引导类,是项目入口,运行main方法就可以启动项目。
- 使用SpringBoot和Spring构建的项目,业务代码编写方式完全一样。
<!--pom.xml-->
<!--SpringBoot父项目依赖管理-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/>
</parent>
<dependencies>
<!--web开发起步依赖-->
<!--导入 spring-boot-starter-web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
/**
* 引导类,spring boot项目的入口
*/
@SpringBootApplication
@ComponentScan("com.xiao") //扫描xiao包,不写这句就是默认是扫描本包
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class,args);
}
}
3、SpringBoot 起步依赖原理分析
起步依赖原理分析
- spring-boot-starter-parent
- spring-boot-starter-web
小结
- 在spring-boot-starter-parent中定义了各种技术的版本信息,组合了一套最优搭配的技术版本。
- 在各种starter中,定义了完成该功能需要的坐标合集,其中大部分版本信息来自于父工程。
- 我们的工程继承parent,引入starter后,通过依赖传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突等问题。
4、SpringBoot 配置
配置文件分类
SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用
application.properties或者application.yml(application.yaml)进行配置。
#第二优先级
#server:
# port: 8082
name: zhangsan
#对象
person:
name: ${name} #参数引用 zhangsan
age: 20
#行内写法
myUser: {name: lisi, age: 20} #这里不要用user,user是系统关键字,表示当前用户,user.name是one_uncle
#数组
array:
- 3
- 6
- 7
#行内写法
array2: [3,6,7]
#纯量
string1: "hello \n world"
string2: 'hello \n world' #单引号表示忽略转义
小结
- SpringBoot提供了2种配置文件类型:properteis 和 yml / yaml
- 默认配置文件名称:application
- 在同一级目录下优先级为:properties > yml > yaml ,如果扫描到相同属性,则会自动忽略优先级低的
YAML
YAML:基本语法
- 大小写敏感
- 数据值前边必须有空格,作为分隔符
- 使用缩进表示层级关系
- 缩进时不允许使用Tab键,只允许使用空格(各个系统 Tab对应的 空格数目可能不同,导致层次混乱)。
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
#
表示注释,从这个字符一直到行尾,都会被解析器忽略
YAML:数据格式
对象(map):键值对的集合。
person:
name: zhangsan
#行内写法
person: {name: zhangsan}
数组:一组按次序排列的值
address:
- beijing
- shanghai
#行内写法
address: [beijing,shanghai]
纯量:单个的、不可再分的值
msg1: 'hello \n world' # 单引忽略转义字符,\n原样输出
msg2: "hello \n world" # 双引识别转义字符,\n会转义成换行
YAML:参数引用
@Value("${name}")
private String myName;
@Value("${myUser.name}")
private String userName;
@Value("${myUser.age}")
private int age;
@Value("${array[0]}")
private int array1;
@Autowired
private Environment environment;
@Autowired
private Person person;
@RequestMapping("/hello5")
public String hello5(){
String array2 = environment.getProperty("array2[2]");
System.out.println(array2);
return "hello SpringBoot 5555";
}
YAML:小结
1) 配置文件类型
- properties:和以前一样
- yml/yaml:注意空格
2) yaml:简洁,以数据为核心
-
基本语法
-
大小写敏感
-
数据值前边必须有空格,作为分隔符
-
使用空格缩进表示层级关系,相同缩进表示同一级
-
-
数据格式
-
对象
-
数组: 使用
-
表示数组每个元素 -
纯量
-
-
参数引用
${key}
读取配置内容
- @Value
- Environment 相当于配置文件的全局变量
- @ConfigurationProperties 让配置内容和对象进行相互绑定
@Component
@ConfigurationProperties(prefix = "person") //声明前缀,就是配置文件中的,不然会读到纯量
public class Person {
private String name;
private int 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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
profile
我们在开发Spring Boot应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址、服务
器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。profile功能就是来进行动态配置切换的。
1) profile配置方式
- 多profile文件方式
- yml多文档方式
2) profile激活方式
- 配置文件
- 虚拟机参数
- 命令行参数
Profile-小结
1) profile是用来完成不同环境下,配置动态切换功能的。
2) profile配置方式
-
多profile文件方式:提供多个配置文件,每个代表一种环境。
-
application-dev.properties/yml 开发环境
-
application-test.properties/yml 测试环境
-
application-pro.properties/yml 生产环境
-
-
yml多文档方式:
- 在yml中使用
---
分隔不同配置
--- server: port: 8081 spring: config: activate: on-profile: dev --- server: port: 8082 spring: config: activate: on-profile: test --- server: port: 8083 spring: config: activate: on-profile: pro ---
#激活配置文件application-dev.properties spring.profiles.active=pro
- 在yml中使用
3) profile激活方式
- 配置文件: 在配置文件
application.properties
中配置:spring.profiles.active=dev
- 虚拟机参数:在VM options 指定:
-Dspring.profiles.active=dev
- 命令行(程序)参数:jar包所在文件夹下cmd
java –jar xxx.jar --spring.profiles.active=dev
,用于无开发环境下使用


内部配置加载顺序
Springboot程序启动时,会从以下位置加载配置文件:
file:./config/
:当前项目下的/config目录下file:./
:当前项目的根目录classpath:/config/
:classpath的/config目录classpath:/
:classpath的根目录classpath:
就是resources文件夹
加载顺序为上文的排列顺序,高优先级配置的属性会生效
外部配置加载顺序
通过官网查看外部属性加载顺序:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
由上往下优先级越来越高
- Default properties (specified by setting ).
SpringApplication.setDefaultProperties
@PropertySource
annotations on your classes. Please note that such property sources are not added to the until the application context is being refreshed. This is too late to configure certain properties such as and which are read before refresh begins.@Configuration
Environment
logging.*
spring.main.*
- Config data (such as files).
application.properties
- A that has properties only in .
RandomValuePropertySource
random.*
- OS environment variables.
- Java System properties ().
System.getProperties()
- JNDI attributes from .
java:comp/env
ServletContext
init parameters.ServletConfig
init parameters.- Properties from (inline JSON embedded in an environment variable or system property).
SPRING_APPLICATION_JSON
- Command line arguments. (命令行参数)
properties
attribute on your tests. Available on@SpringBootTest
and the test annotations for testing a particular slice of your application.@TestPropertySource
annotations on your tests.- Devtools global settings properties in the directory when devtools is active.
$HOME/.config/spring-boot
5、SpringBoot 整合其他框架
1、SpringBoot整合Junit
案例:实现步骤
① 搭建SpringBoot工程
② 引入starter-test起步依赖 (快速创建的springboot项目自带)
③ 编写测试类
④ 添加测试相关注解
- @RunWith(SpringRunner.class) 新版spring boot已经不需要RunWith了
- @SpringBootTest(classes = 启动类.class) 如果和引导类(项目启动入口)在一个包下,则不需要指定启动类
⑤ 编写测试方法
2、SpringBoot整合Redis
案例:实现步骤
① 搭建SpringBoot工程
② 引入redis起步依赖
③ 配置redis相关属性
④ 注入RedisTemplate模板
⑤ 编写测试方法,测试
@SpringBootTest
class SpringBootRedisApplicationTests {
//本机redis不用配置文件,默认6379端口号
//@Qualifier("redisTemplate") //如果不使用redisTemplate,则需要这句,结合@Autowired一起使用用于根据名称进行依赖注入
@Autowired
private RedisTemplate redisTemplate; //必须得是redisTemplate,不然找不到
@Test
void testSet() {
//存入数据
BoundValueOperations boundValueOperations = redisTemplate.boundValueOps("name"); //name是key
boundValueOperations.set("zhangsan"); //zhangsan是value
}
@Test
void testGet() {
//获取数据
BoundValueOperations boundValueOperations = redisTemplate.boundValueOps("name");
Object name = boundValueOperations.get();
System.out.println(name);
}
}
application.properties
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000ms
3、SpringBoot整合MyBatis
案例:实现步骤
① 搭建SpringBoot工程
//引导类的包扫描
@SpringBootApplication
@MapperScan("com.xiao") //这个很重要,必须有,把mapper扫描进容器中
@ComponentScan("com.xiao") //这个可以没有,没有该注解会使@Autowired的地方报红,但是不影响运行
public class SpringBootMyBatisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMyBatisApplication.class, args);
}
}
② 引入mybatis起步依赖,添加mysql驱动

③ 编写DataSource和MyBatis相关配置
#application.yml
# datasource
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: whyzazn
④ 定义表和实体类
public class User {
private int id;
private String username;
private String password;
...
}
⑤ 编写dao和mapper文件/纯注解开发
注解方式
@Mapper
public interface UserMapper {
@Select("select * from user")
List<User> findAll();
}
mapper文件方式
@Mapper
public interface UserXmlMapper {
List<User> findAll();
}
<!--userMapper.xml-->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiao.mapper.UserXmlMapper">
<select id="findAll" resultType="user">
select * from user
</select>
</mapper>
#application.yml
# mybatis配置
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml #映射文件路径
# config-location: 指定mybatis的核心配置文件
type-aliases-package: com.xiao.domain #配置别名
⑥ 测试
@SpringBootTest
class SpringBootMyBatisApplicationTests {
@Autowired
private UserMapper userMapper;
@Autowired
private UserXmlMapper userXmlMapper;
/**
* 注解方式
*/
@Test
void testFindAll1() {
List<User> userList = userMapper.findAll();
for (User user : userList) {
System.out.println(user);
}
}
/**
* 配置文件方式
*/
@Test
void testFindAll2() {
List<User> userList = userXmlMapper.findAll();
for (User user : userList) {
System.out.println(user);
}
}
}
4、整合dubbo
6、SpringBoot原理分析
1、SpringBoot 自动配置
1、Condition
Condition 是在Spring 4.0 增加的条件判断功能,通过这个可以功能可以实现选择性的创建 Bean 操作。
思考
SpringBoot是如何知道要创建哪个Bean的?比如SpringBoot是如
何知道要创建RedisTemplate的? 实际上就是通过condition判断的
案例:需求
在 Spring 的 IOC 容器中有一个 User 的 Bean,现要求:
-
导入Jedis坐标后,加载该Bean,没导入,则不加载。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
将类的判断定义为动态的。判断哪个字节码文件存在可以动态指定。
@Configuration public class UserConfig { @Bean @Conditional(ClassCondition.class)//返回值是false,则不会创建该Bean public User user(){ return new User(); } }
自己写条件类,把条件写死
public class ClassCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //导入jedis坐标后,返回true,创建Bean //判断该文件是否存在 boolean flag = true; try { Class<?> cls = Class.forName("org.springframework.boot.autoconfigure.data.redis.RedisProperties$Jedis"); } catch (ClassNotFoundException e) { //加载不到 flag = false; e.printStackTrace(); } return flag; } }
或者自定义注解,动态写条件
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional(ClassCondition.class) public @interface ConditionOnClass { String[] value(); }
@Configuration public class UserConfig { @Bean //@Conditional(ClassCondition.class)//返回值是false,则不会创建该Bean @ConditionOnClass("org.springframework.boot.autoconfigure.data.redis.RedisProperties$Jedis") public User user(){ return new User(); } }
public class ClassCondition implements Condition { /** * * @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象 * @param metadata 注解的元对象。可以用于获取注解定义的属性值 * @return */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //导入指定的坐标后,返回true,创建Bean //获取注解传入的属性值 Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName()); String[] value = (String[]) map.get("value"); //判断该文件是否存在 boolean flag = true; try { for (String className : value) { Class<?> cls = Class.forName(className); } } catch (ClassNotFoundException e) { //加载不到 flag = false; e.printStackTrace(); } return flag; } }
@SpringBootApplication @ComponentScan("com.xiao") //包扫描 public class SpringBootConditionApplication { public static void main(String[] args) { //启动springboot的应用,返回spring IOC容器 ConfigurableApplicationContext context = SpringApplication.run(SpringBootConditionApplication.class, args); //获取Bean Object user = context.getBean("user"); System.out.println(user); } }
Condition – 小结
自定义条件:
① 定义条件类:自定义类实现Condition接口,重写 matches 方法,在 matches 方法中进行逻辑判断,返回
boolean值 。 matches 方法两个参数:
- context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。
- metadata:元数据对象,用于获取注解属性。
② 判断条件: 在初始化Bean时,使用 @Conditional(条件类.class)注解
SpringBoot 提供的常用条件注解:
ConditionalOnProperty
:判断配置文件中是否有对应属性和值才初始化BeanConditionalOnClass
:判断环境中是否有对应字节码文件才初始化BeanConditionalOnMissingBean
:判断环境中没有对应Bean才初始化Bean
2、切换内置web服务器
SpringBoot的web环境中默认使用tomcat作为内置服务器,其实SpringBoot提供了4中内置服务器供我们选择,我们可
以很方便的进行切换。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
<!--排除tomcat依赖-->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--引入其他服务器依赖Jetty\Netty\Undertow-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
3、@Enable*注解
SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注
解导入一些配置类,实现Bean的动态加载。
@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 {};
}
思考
SpringBoot 工程是否可以直接获取jar包中定义的Bean?
不可以,需要使用 @ComponentScan 扫描Bean所在目录 或者 @Import 导入包
4、@Import注解
@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。
而@Import提供4中用法:
① 导入Bean // @Import(User.class)
② 导入配置类 // @Import(UserConfig.class)
③ 导入 ImportSelector(接口) 实现类。一般用于加载配置文件中的类
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.xiao.domain.User","com.xiao.domain.Role"};
}
}
//在引导类上引入
@Import(MyImportSelector.class)
④ 导入 ImportBeanDefinitionRegistrar(接口) 实现类。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
//在IOC容器注册Bean
registry.registerBeanDefinition("user",beanDefinition);
}
}
//在引导类上引入
@Import(MyImportBeanDefinitionRegistrar.class)
4、@EnableAutoConfiguration 注解
流程
@EnableAutoConfiguration
注解内部使用@Import(AutoConfigurationImportSelector.class)
来加载配置类。- 配置文件位置:
META-INF/spring.factories
,该配置文件中定义了大量的配置类,当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean - 并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean
5、自定义起步依赖案例(重要)
案例:需求
自定义redis-starter。要求当导入redis坐标时,SpringBoot自动创建Jedis的Bean。
案例:实现步骤
① 创建 redis-spring-boot-autoconfigure
模块
② 创建 redis-spring-boot-starter
模块,依赖 redis-spring-boot-autoconfigure
的模块
<dependency>
<groupId>com.xiao</groupId>
<artifactId>redis-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
③ 在 redis-spring-boot-autoconfigure
模块中初始化 Jedis 的Bean。并定义META-INF/spring.factories
文件
④ 在测试模块中引入自定义的 redis-spring-boot-starter
依赖,测试获取Jedis 的Bean,操作 redis。
redis-spring-boot-autoconfigure
自动配置模块
RedisAutoConfiguration.class
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass(Jedis.class)//保证Jedis在的时候才去加载Jedis的Bean
public class RedisAutoConfiguration {
/**
* 提供jedis Bean
*/
@Bean
@ConditionalOnMissingBean(name = "jedis") //如果用户已经自定义了jedis的Bean,就不加载,用他自己定义的
public Jedis jedis(RedisProperties redisProperties){
System.out.println("自动生成Jedis Bean......");
return new Jedis(redisProperties.getHost(),redisProperties.getPort());
}
}
RedisProperties.class
//以Redis开头的配置(包括配置类和其他配置文件中带redis前缀的参数)会和该配置文件相绑定
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
private String host = "localhost";
private int port = 6379;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
resource/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.xiao.configure.RedisAutoConfiguration
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--引入 jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
redis-spring-boot-starter
起步依赖
pom.xml
<dependencies>
<!--引入configure-->
<dependency>
<groupId>com.xiao</groupId>
<artifactId>redis-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
SpringBoot_enable 需要启动的项目
引导类
@SpringBootApplication
public class SpringBootEnableApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringBootEnableApplication.class, args);
Jedis jedis = context.getBean(Jedis.class);
System.out.println(jedis);//BinaryJedis{Connection{DefaultJedisSocketFactory{localhost:6379}}}
}
}
pom.xml
<!--引入自定义的Redis起步依赖-->
<dependency>
<groupId>com.example</groupId>
<artifactId>redis-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
2、SpringBoot 监听机制
1、Java 监听机制
SpringBoot 的监听机制,其实是对Java提供的事件监听机制的封装。
Java中的事件监听机制定义了以下几个角色:
① 事件:Event,继承 java.util.EventObject 类的对象
② 事件源:Source ,任意对象Object
③ 监听器:Listener,实现 java.util.EventListener 接口 的对象
2、SpringBoot 监听机制
SpringBoot 在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成
一些操作。
-
ApplicationContextInitializer
、SpringApplicationRunListener
-
需要进行配置,在resources/META-INF/spring.factories里,所以不用加@Component
-
#接口全路径名 = 自定义监听器全路径名 org.springframework.context.ApplicationContextInitializer=com.xiao.listener.listener.MyApplicationContextInitializer org.springframework.boot.SpringApplicationRunListener=com.xiao.listener.listener.MySpringApplicationRunListener
-
-
CommandLineRunner
、ApplicationRunner
- 加入容器后@Component,当项目启动后执行,作用一样,只用其中一个就行

1、ApplicationContextInitializer
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("ApplicationContextInitializer...initialize");
}
}
2、SpringApplicationRunListener
public class MySpringApplicationRunListener implements SpringApplicationRunListener {
/**
* 构造方法
* @param application
* @param args
*/
public MySpringApplicationRunListener(SpringApplication application, String[] args) {
}
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("SpringApplicationRunListener...starting...项目启动中");
SpringApplicationRunListener.super.starting(bootstrapContext);
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("SpringApplicationRunListener...environmentPrepared...环境对象开始准备");
SpringApplicationRunListener.super.environmentPrepared(bootstrapContext, environment);
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener...contextPrepared...上下文对象开始准备");
SpringApplicationRunListener.super.contextPrepared(context);
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener...contextLoaded...上下文对象开始加载,准备需要的Bean");
SpringApplicationRunListener.super.contextLoaded(context);
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("SpringApplicationRunListener...started...上下文对象加载完成");
SpringApplicationRunListener.super.started(context, timeTaken);
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("SpringApplicationRunListener...ready...项目准备完毕");
SpringApplicationRunListener.super.ready(context, timeTaken);
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("SpringApplicationRunListener...failed...项目启动失败");
SpringApplicationRunListener.super.failed(context, exception);
}
}
3、CommandLineRunner
/**
* 当项目启动后执行,可以完成缓存预热的操作
*/
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner...run");
//打印参数
System.out.println(Arrays.asList(args));
}
}
4、ApplicationRunner
/**
* 当项目启动后执行,可以完成缓存预热的操作
*/
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner...run");
//打印参数
System.out.println(Arrays.asList(args.getSourceArgs()));
}
}
5、未写spring.factories时,启动引导类后,只有两个监听器被调用
ApplicationRunner...run
[name=xiao]
CommandLineRunner...run
[name=xiao]
6、写了spring.factories后
SpringApplicationRunListener...starting...项目启动中
SpringApplicationRunListener...environmentPrepared...环境对象开始准备
ApplicationContextInitializer...initialize
SpringApplicationRunListener...contextPrepared...上下文对象开始准备
SpringApplicationRunListener...contextLoaded...上下文对象开始加载,准备需要的Bean
SpringApplicationRunListener...started...上下文对象加载完成
ApplicationRunner...run
[name=xiao]
CommandLineRunner...run
[name=xiao]
SpringApplicationRunListener...ready...项目准备完毕
3、SpringBoot 启动流程分析
太难了,追源码

7、SpringBoot 监控
1、SpringBoot 监控概述
SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性、日志信息等。
2、SpringBoot 监控使用
使用步骤
① 导入依赖坐标,也可以在创建项目时Ops里面加入依赖Spring Boot Actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
② 访问http://localhost:8080/acruator
# 开启健康检查的完整信息
management.endpoint.health.show-details=always
# 将所有的监控endpoint暴露出来
management.endpoints.jmx.exposure.include=*
访问localhost:8080/actuator/health
页面展示
{"status":"UP","components":{"diskSpace":{"status":"UP","details":{"total":457083711488,"free":218772336640,"threshold":10485760,"exists":true}},"ping":{"status":"UP"}}}
3、SpringBoot 监控使用
路径 | 描述 |
---|---|
/beans | 描述应用程序上下文里全部的Bean,以及它们的关系 |
/env | 获取全部环境属性 |
/env/ | 根据名称获取特定的环境属性值 |
/health | 报告应用程序的健康指标,这些值由HealthIndicator的实现类提供 |
/info | 获取应用程序的定制信息,这些信息由info打头的属性提供 |
/mappings | 描述全部的URI路径,以及它们和控制器(包含Actuator端点)的映射关系 |
/metrics | 报告各种应用程序度量信息,比如内存用量和HTTP请求计数 |
/metrics/ | 报告指定名称的应用程序度量值 |
/trace | 提供基本的HTTP请求跟踪信息(时间戳、HTTP头等) |
4、SpringBoot 监控 - Spring Boot Admin
2.6版本以上已经不知道怎么向服务器注册了
Spring Boot Admin Reference Guide (codecentric.github.io)
- Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序。
- Spring Boot Admin 有两个角色,客户端(Client)和服务端(Server)。
- 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册
- Spring Boot Admin Server 的UI界面将Spring Boot Admin Client的Actuator Endpoint上的一些监控信息。
使用步骤
admin-server:
① 创建 admin-server 模块
② 导入依赖坐标 admin-starter-server,也可以创建时在Ops直接勾选
③ 在引导类上启用监控功能 @EnableAdminServer
admin-client:
① 创建 admin-client 模块
② 导入依赖坐标 admin-starter-client,也可以创建时在Ops直接勾选
③ 配置相关信息:server地址等
④ 启动server和client服务,访问server
8、SpringBoot 项目部署
SpringBoot 项目开发完毕后,支持两种方式部署到服务器:
① jar包(官方推荐)
在jar包所在目录执行cmd
java -jar SpringBoot_profiles-0.0.1-SNAPSHOT.jar
② war包
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南