柏竹 柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档

柏竹

奋斗柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档
  • Java基础

  • JavaWeb

  • 拓展技术

  • 框架技术

  • 数据库

  • 数据结构

  • Spring

  • SpringMVC

  • SpringBoot

    • SpringBoot
    • SpringBoot3基础特性
    • SpringBoot3核心原理
      • 事件与监听器
        • 生命周期监听
        • 事件触发时机
        • 事件监听
        • 前置概念
        • ApplicationListener监听
        • 事件驱动
      • 自动配置
      • @SpringBootApplication
      • 完整运作流程
      • 自定义Starter
    • 框架整合

    • SpringBoot部署
  • SpringClound

  • Ruoyi-Vue-Plus

  • 后端
  • SpringBoot
柏竹
2023-06-09
目录

SpringBoot3核心原理

# 事件与监听器

# 生命周期监听

生命周期会监听SpringBoot运作过程是周期 , 监听需要重写 SpringApplicationRunListener接口

SpringApplicationRunListener接口重写的方法

方法 参数说明 说明
starting() ConfigurableBootstrapContext : 引导整个项目启动器 引用开始就调用(监听器管理一旦加载完运行)
environmentPrepared() ConfigurableBootstrapContext : 上下文引导
ConfigurableEnvironment : 环境
环境准备完成 (ico容器未创建)
contextPrepared() ConfigurableApplicationContext : 应用程序上下文 ioc容器创建准备完成 , 并关闭引用启动器 (但 sources主配置类 未加载)
contextLoaded() ConfigurableApplicationContext : 应用程序上下文 ioc容器加载 (主配置类加载) , 但 ico容器的Bean未加载
started() ConfigurableApplicationContext : 应用程序上下文
Duration : 启动程序所需的时间 或 null
ioc容器刷新 (所有Bean初始化) , 但 runner 未调用
ready() ConfigurableApplicationContext : 应用程序上下文
Duration : 启动程序所需的时间 或 null
ioc容器刷新 , runner 也调用完成
failed() ConfigurableApplicationContext : 应用程序上下文
Throwable : 失败
捕捉starting()之后的步骤异常情况

SpringBoot生命周期运作流程 : (分三大部分)

  1. 引导部分

    1. staring : 启动
    2. environmentPrepared : 环境准备完成
  2. 启动部分

    1. contextPrepared : ioc创建准备完成 , 主程序未加载
    2. contextLoaded : ioc加载 , 并未刷新
    3. started : ioc刷新 runner未调用
    4. ready : ioc刷新 runner未调用完成
    • failed : 启动失败 (失败情况下)
  3. 运行部分

    contxt.isRunning() 运行中

应用步骤 :

  1. 创建 自定义监听类 MyApplistener实现 SpringApplicationRunListener接口

  2. 重写接口所有方法 (打印查看运行状况)

  3. 新建文件 加载文件 /resources/META-INF/spring.factories

    # 后面写的是 自定义监听类全限定名路径
    org.springframework.boot.SpringApplicationRunListener=com.sans.demo2.listener.MyAppListener
    
  4. 运行Application类 查看控制台打印即可

未重写默认是以下配置

org.springframework.boot.SpringApplicationRunListener=\org.springframework.boot.context.event.EventPublishingRunListener	

在Application启动类中跟踪可以看到 , 该方法是根据指定路径配置文件进行加载的监听器

image-20230607170145329

# 事件触发时机

SpringBoot在启动的时候会有很多事件触发 , 这些事件的触发可以自定义定义一些业务实现

可以通过上面应用的 生命周期应用的 SpringApplicationRunListener 作为简单的实例去理解!

各种监听器回调

类/接口 感知范围 引用 说明
BootstrapRegistryInitializer 引导初始化 - META-INF/spring.factories 用于在应用启动很早期进行一些初始化逻辑
ApplicationContextInitializer Ioc容器初始化 - META-INF/spring.factories 用于在应用Ioc容器创建前进行一些定制化
ApplicationListener 全局事件感知 - META-INF/spring.factories
- @EventListener
- Ioc容器注册
用于感知SpringBoot应用全局事件 , 并执行对应逻辑
SpringApplicationRunListener 生命周期感知 - META-INF/spring.factories 用于感知SpringBoot应用的启动阶段
ApplicationRunner 应用就绪Ready - Ioc容器注册 用于应用启动完成后执行一些初始化逻辑 , 只执行一次
CommandLineRunner 应用就绪Ready - Ioc容器注册 同ApplicationRunner , 但这是面向命令行参数的 , 用来解析命令行参数

实战应用

  • 项目启动前 采用 : BootstrapRegistryInitializer/ApplicationContextInitializer
  • 项目启动后 采用 : ApplicationRunner/CommandLineRunner
  • 生命周期 采用 :SpringApplicationRunListener
  • 全局事件 采用 : ApplicationListener

# 事件监听

# 前置概念

监听器机制是Spring框架提供的一种主体对象状态变化的机制 . 当被监听的对象发生变化时 , 相关的监听器就会被通知 , 进行一些相应的处理

比如我们可以用监听器监听Spring容器的启动和刷新事件 , 然后在事件发生后做一些初始化操作

监听器三大组件 :

  • 事件(ApplicationEvent)
  • 事件监听器(ApplicationListener)
  • 事件发布者(ApplicationEventPublisher)

# ApplicationListener监听

ApplicationListener触发的事件 分别有9个 又称 9大事件 :

顺序 事件 时机
1 ApplicationStartingEvent 应用启动但未做任何事情 , 除过注册listeners and initializers
2 ApplicationEnvironmentPreparedEvent Environment准备完成 , 可以获取环境变量等信息
3 ApplicationContextInitializedEvent ApplicationContext初始化完成
4 ApplicationPreparedEvent ApplicationContext准备完成 , Bean定义加载完成
5 ApplicationStartedEvent 应用启动完成
6 AvailabilityChangeEvent 应用可用性变化 LivenessState.CORRECT探针应用存活
7 ApplicationReadyEvent 应用启动完成 , ApplicationContext也加载完成
8 AvailabilityChangeEvent 应用可用性变化 ReadinessState.ACCEPTING_TRAFFIC就绪探针
9 ApplicationFailedEvent 应用启动失败

示例 : 所有事件时机Demo (opens new window)

生命周期流程图 :

image-20230609201758639

事件&监听器 时序图 :

image-20230609173630370

# 事件驱动

事件驱动我们不难理解 , 前面前置的三大监听组件可以得知 , 事件发布者 广播发布 事件 , 监听器会接收与之对应的对象类型

  • 发布事件 : ApplicationEventPublisherAware接口实现 , 重写自动回调获取API操作接口
  • 监听事件 : ApplicationListener<事件对象>接口实现 , 重写触发事件方法
  • 事件对象 : ApplicationEvent继承该类 , 标识事件监听对象

监听方式

  • ApplicationListener接口 实现 , 接口的泛型为 事件对象 , 并重写 onApplicationEvent()方法 触发监听事件
  • @EventListener注解 实现 , 注解方法上 , 参数必须为监听的 事件对象

示例 : Demo案例 (opens new window)

假如我要实现登录事件 , 实现 登录后欢迎 和 随机发放优惠券 功能 , 通过事件进行触发这些服务

事件对象 点击展开

省略User对象实体

public class LoginSuccessEvent extends ApplicationEvent {
    public LoginSuccessEvent(User user) {
        super(user);
    }
}
事件发布者 点击展开
@Component
public class EventPublisher implements ApplicationEventPublisherAware {

    ApplicationEventPublisher applicationEventPublisher;

    /**
     * 底层自动回调传入API接口操作
     * @param applicationEventPublisher 对象要使用的事件发布者
     */
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    /**
     * 所有事件均可发送
     * @param event
     */
    public void sendEvent(ApplicationEvent event) {
        // 调用底层API发送事件
        applicationEventPublisher.publishEvent(event);
    }

}
Contorller层登录触发 点击展开
@RestController
public class LoginController {

    @Resource
    private EventPublisher eventPublisher;

    @GetMapping("/login")
    public String login(String username, String password) {
        // 创建事件
        LoginSuccessEvent event = new LoginSuccessEvent(new User(username, password));
        // 发布事件
        eventPublisher.sendEvent(event);
        
        return "[" + username + "]登录成功";
    }

}
监听事件&登录欢迎 点击展开

通过 ApplicationListener接口 实现监听

@Service
public class AccountService implements ApplicationListener<LoginSuccessEvent> {

    public void welcome(String username) {
        System.out.println("欢迎 "+username+" 到来!");
    }

    @Override
    public void onApplicationEvent(LoginSuccessEvent event) {
        User user = (User) event.getSource();
        String username = user.getUsername();
        System.out.println( username + "监听收到事件!");
        welcome(username);
    }
}
监听事件&发送优惠券 点击展开

通过 @EventListener注解 实现监听

@Service
public class CouponService {

    public void sendCoupon(String username) {
        System.out.println(username+" 随机获取一张优惠券!");
    }

    @EventListener
    public void onEvent(LoginSuccessEvent event) {
        User user = (User) event.getSource();
        String username = user.getUsername();
        System.out.println( username+ "监听收到事件!");
        sendCoupon(username);
    }

}

# 自动配置

SpringBoot 非常重要的一个特性 , 可以根据你添加的jar依赖自动配置 , 例如引入有关 starter相关的Spring应用 spring-boot-starter-web , spring-boot-starter-redis ...

意图 : 通过外部jar包自动加载Bean , 搭配 @ConditionalOnClass、@ConditionalOnBean 实现

自定义自动配置引用步骤 :

  1. 导入依赖 starter 和 autoconfigure
  2. 创建类路径文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 它在运行后会寻找该类路径进行执行
  3. 创建 配置类 xxxAutoConfiguration , 添加 @AutoConfiguration注解
  4. (可选) 配置与属性对应注入 @EnableConfigurationProperties注解 (注解值指定 配置属性类)
  5. (可选) 创建 配置属性类 xxxProperties , 添加 @ConfigurationProperties注解 (注解值指定 配置文件前缀绑定)
  6. (可选) 配置属性类 定义成员变量属性 , 后缀为成员属性名进行绑定
  7. 在 配置类上写个 @Bean初始实例化 并且参数引用 配置属性类
  8. 测试引用

SPI机制示例 : 自动配置Demo (opens new window) , 日志案例Demo (opens new window)

SPI机制

该机制用于 动态发现和加载组件 , 在运行程序后加载

# @SpringBootApplication

@SpringBootApplication注解使启动类具有配置类、自动配置和组件扫描的功能 , 从而简化了Spring Boot应用的配置和开发

@SpringBootConfiguation . 标识配置类(装配Ioc容器)

@EnableAutoConfiguation . 开启自动配置

  • @AutoConfigurationPackage 扫描主程序包 , 加载自己的组件

    • @Import({AutoConfigurationPackages.Registrar.class}) . 主程序所在的包路径下的所有其他包以及子包
  • @Import({AutoConfigurationImportSelector.class}) . 加载自动配置类 , 加载starter导入的组件

    扫描SPI文件加载 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@ComponentScan . 排除组件 (排除已经扫描的配置类 和 自动配置类)

# 完整运作流程

image-20230609173630370

断点理解技巧 :

  • 根据启动类 @SpringBootApplication注解 入手跟踪 @Import注解
  • 断点跟踪 方法栈顺序跟踪
  • 反向思维 : Bean构造方法 , ApplicationListener接口 事件全感知 跟踪

# 自定义Starter

虽说官方提供了很多Starter , 也并非能满足所有场景 , 假如项目有个特殊的需求更改原生Starter进行封装 , 那么其他模块也会引用该模块封装的API

大致步骤 :

  1. 抽离业务代码

  2. 配置价值模式

    • 使用 @EnableXxx机制 (手动注解引用)

      使用以上注解搭配 @Import 加载配置类 进行统一配置

    • 使用SPI机制 (完全自动引入)

      META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件 自动加载配置类

实际业务场景

需求 : 通过导入此 stater 实现接口具有打招呼功能 , 问候语携带人名 (人名从配置信息中读取)

示例 : SPI/@Enable 实现案例 (opens new window)

#SpringBoot

← SpringBoot3基础特性 SpringBoot SpringMVC 整合→

最近更新
01
HTTPS自动续签
10-21
02
博客搭建-简化版(脚本)
10-20
03
ruoyi-vue-plus-部署篇
07-13
更多文章>
Theme by Vdoing | Copyright © 2019-2024 | 桂ICP备2022009417号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式