首页 > 其他分享 >【知识整理】Springboot启动扩展点

【知识整理】Springboot启动扩展点

时间:2023-08-24 14:48:28浏览次数:36  
标签:Springboot 知识 扩展 bean 执行 方法 public InstantiationAwareBeanPostProcessor NonNull

SpringBoot启动扩展点整理

1. 前言

​ 在Springboot服务启动阶段,Springboot提供了许多扩展点。在实际的业务开发过程中,部分特殊的业务需求需要再Springboot服务启动过程中动态的加载配置或者执行业务处理,特此将常用的Springboot启动扩展点做一个简单的整理。

2. 准备阶段


2.1 EnvironmentPostProcessor

  • 接口路径

org.springframework.boot.env.EnvironmentPostProcessor

  • 官方说明
    • 允许在刷新应用程序上下文之前自定义应用程序的Environment
    • 需要在META-INF/spring.factories文件中定义

Allows for customization of the application's {@link Environment} prior to the application context being refreshed.

EnvironmentPostProcessor implementations have to be registered in {@code META-INF/spring.factories}, using the fully qualified name of this class as the key.

  • 应用场景

​ 可以加载自定义的配置文件并添加至Environment中

  • 回调时机

image-20230609164107625

  • 代码示例
public class DemoEnvironmentPostProcessor implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(@NonNull ConfigurableEnvironment environment, @NonNull SpringApplication application) {
        System.out.println(">>> 执行EnvironmentPostProcessor.postProcessEnvironment()方法");
    }
}
  • 生效方式

​ 在META-INF/spring.factories文件中添加内容

org.springframework.boot.env.EnvironmentPostProcessor = com.example.demo.extension.DemoEnvironmentPostProcessor

2.2 ApplicationContextInitializer

  • 接口路径

org.springframework.context.ApplicationContextInitializer

  • 应用场景

​ Spring会在容器刷新之前调用此类的initialize方法,可以激活一些配置或者获取Enviroment进行一些业务处理。

  • 回调时机

image-20230620145523093

  • 代码示例
public class DemoApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(@NonNull ConfigurableApplicationContext applicationContext) {
        System.out.println(">>> 执行ApplicationContextInitializer.initialize()方法");
    }
}
  • 生效方式

    META-INF/spring.factories文件中添加内容

    org.springframework.context.ApplicationContextInitializer = com.example.demo.extension.DemoApplicationContextInitializer
    

3. 刷新上下文容器阶段

​ 这部分的接口在执行refreshContext(context)方法刷新上下文的过程中回调。

image-20230620155625576

3.1 BeanDefinitionRegistryPostProcessor

  • 接口路径

org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor

  • 应用场景

​ 这个接口在读取项目中的beanDefinition之后执行,提供一个补充的扩展点,动态注册自己的beanDefinition,可以加载classpath之外的bean。

  • 回调时机

image-20230620155755420

  • 代码示例
@Component
public class DemoBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(@NonNull BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println(">>> 执行BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法");
    }

    @Override
    public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println(">>> 执行BeanDefinitionRegistryPostProcessor.postProcessBeanFactory()方法");
    }
}

3.2 BeanFactoryPostProcessor

  • 接口路径

org.springframework.beans.factory.config.BeanFactoryPostProcessor

  • 应用场景

​ 这个接口是beanFactory的扩展接口,调用时机在spring在读取beanDefinition信息之后,实例化bean之前。在这个时机,用户可以通过实现这个扩展接口来自行处理一些东西,比如修改已经注册的beanDefinition的元信息。

  • 回调时机

​ 在AbstractApplicationContext类的refresh方法中被执行。

image-20230621085016488

  • 代码示例
@Component
public class DemoBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println(">>> 执行 BeanFactoryPostProcessor.postProcessBeanFactory()方法");
    }
}

3.3 BeanFactoryAware和EnvironmentAware

  • 接口路径

org.springframework.beans.factory.BeanFactoryAware

org.springframework.context.EnvironmentAware

  • 应用场景

​ 在bean实例化和属性注入之后执行,可以在bean初始化之前注入BeanFactoryEnvironment等在初始化阶段使用。

  • 回调时机

​ 在AbstractAutowireCapableBeanFactory类的createBean方法创建bean的过程中执行。

  • 代码示例
@Component
public class DemoBeanFactoryAware implements BeanFactoryAware {

    @Override
    public void setBeanFactory(@NonNull BeanFactory beanFactory) throws BeansException {
        System.out.println(">>> 执行BeanFactoryAware.setBeanFactory()方法");
    }
}
@Component
public class DemoEnvironmentAware implements EnvironmentAware {

    @Override
    public void setEnvironment(@NonNull Environment environment) {
        System.out.println(">>> 执行EnvironmentAware.setEnvironment()方法");
    }
}

3.4 InstantiationAwareBeanPostProcessor

  • 接口路径

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor

  • 应用场景

InstantiationAwareBeanPostProcessor接口在BeanPostProcessor接口的基础上又扩展了3个方法,共包含5个方法,可以在bean的实例化前后,属性注入阶段以及初始化前后进行业务处理。例如Springboot中就是通过BeanPostProcessor的实现类来解析bean中带有@KafkaListener注解的方法来注册Kafka容器。

  • 回调时机

    • postProcessBeforeInstantiation方法:在bean实例化之前执行

    • postProcessAfterInstantiation方法:在bean实例化之后执行

    • postProcessProperties方法:在bean属性注入阶段执行

    • postProcessBeforeInitialization方法:在bean初始化之前执行

    • postProcessAfterInitialization方法:在bean初始化之后执行

  • 代码示例

@Component
public class DemoInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(@NonNull Class<?> beanClass, @NonNull String beanName) throws BeansException {
        if (beanClass == DemoService.class) {
            System.out.println(">>> 执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法");
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(@NonNull Object bean, @NonNull String beanName) throws BeansException {
        if (bean instanceof DemoService) {
            System.out.println(">>> 执行 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()方法");
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
    }

    @Override
    public PropertyValues postProcessProperties(@NonNull PropertyValues pvs, @NonNull Object bean, @NonNull String beanName) throws BeansException {
        if (bean instanceof DemoService) {
            System.out.println(">>> 执行 InstantiationAwareBeanPostProcessor.postProcessProperties()方法");
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
    }

    @Override
    public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
        if (bean instanceof DemoService) {
            System.out.println(">>> 执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization()方法");
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
        if (bean instanceof DemoService) {
            System.out.println(">>> 执行 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization()方法");
        }
        return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

3.5 @PostConstruct注解

  • 注解路径

javax.annotation.PostConstruct

  • 应用场景

​ 可以在bean的初始化阶段执行初始化方法进行业务处理。

  • 回调时机

​ 在AbstractAutowireCapableBeanFactory类的createBean方法创建bean的过程中InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization方法中执行。

image-20230621092642560

  • 代码示例
@Service
public class DemoService {

    @PostConstruct
    public void init() {
        System.out.println(">>> 执行 @PostConstruct注解方法");
    }
}

3.6 InitializingBean

  • 接口路径

org.springframework.beans.factory.InitializingBean

  • 应用场景

​ 同样可以在执行bean初始化过程中执行业务处理。

  • 回调时机

​ 在AbstractAutowireCapableBeanFactory类的createBean方法创建bean的过程中AbstractAutowireCapableBeanFactory类的initializeBean方法中执行。

image-20230621093251221

  • 代码示例
@Component
public class DemoInitializingBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(">>> 执行InitializingBean.afterPropertiesSet()方法");
    }
}

3.7 SmartInitializingSingleton

  • 接口路径

org.springframework.beans.factory.SmartInitializingSingleton

  • 应用场景

​ 在对所有单例对象初始化完毕后,做一些后置的业务处理。

  • 回调时机

​ 在类DefaultListableBeanFactorypreInstantiateSingletons的方法中执行。

image-20230824100454842

  • 代码示例
@Component
public class DemoSmartInitializingSingleton implements SmartInitializingSingleton {

    @Override
    public void afterSingletonsInstantiated() {
        System.out.println(">>> 执行SmartInitializingSingleton.afterSingletonsInstantiated()方法");
    }
}

3.8 SmartLifecycle

  • 接口路径

org.springframework.context.SmartLifecycle

  • 应用场景

​ 在对所有单例对象初始化完毕后,做一些后置的业务处理。SmartLifecycleLifecycle接口的基础上,扩展了3个方法。

image-20230824101141579

​ 其中,isAutoStartup()方法返回true时,Bean将在容器完成刷新阶段执行Lifecycle接口的start()方法;getPahase()方法用于返回SmartLifecycle的优先级。可结合配置文件的配置项来指定SmartLifecycle是否自动启动及启动的优先级。

  • 回调时机

​ 在AbstractApplicationContext类的finishRefresh方法中执行。

image-20230824101817686

  • 代码示例
@Component
public class DemoSmartLifecycle implements SmartLifecycle {

    @Override
    public void start() {
        System.out.println(">>> 执行SmartLifecycle.start()方法");
    }

    @Override
    public void stop() {

    }

    @Override
    public boolean isRunning() {
        return false;
    }
}

4. 执行顺序

​ 通过日志可以看到各个扩展点的实际执行顺序。

>>> 执行EnvironmentPostProcessor.postProcessEnvironment()方法

>>> 执行ApplicationContextInitializer.initialize()方法

>>> 执行 BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法

>>> 执行 BeanDefinitionRegistryPostProcessor.postProcessBeanFactory()方法

>>> 执行 BeanFactoryPostProcessor.postProcessBeanFactory()方法

>>> 执行 BeanFactoryAware.setBeanFactory()方法
 
>>> 执行 EnvironmentAware.setEnvironment()方法

>>> 执行 InitializingBean.afterPropertiesSet()方法

>>> 执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法

>>> 执行 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()方法

>>> 执行 InstantiationAwareBeanPostProcessor.postProcessProperties()方法

>>> 执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization()方法

>>> 执行 @PostConstruct注解方法

>>> 执行 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization()方法

>>> 执行 SmartInitializingSingleton.afterSingletonsInstantiated()方法

>>> 执行 SmartLifecycle.start()方法

标签:Springboot,知识,扩展,bean,执行,方法,public,InstantiationAwareBeanPostProcessor,NonNull
From: https://www.cnblogs.com/little-code-farmer/p/17654055.html

相关文章

  • 超越界限:大模型应用领域扩展,探索文本分类、文本匹配、信息抽取和性格测试等多领域应用
    超越界限:大模型应用领域扩展,探索文本分类、文本匹配、信息抽取和性格测试等多领域应用随着ChatGPT和GPT-4等强大生成模型出现,自然语言处理任务方式正在逐步发生改变。鉴于大模型强大的任务处理能力,未来我们或将不再为每一个具体任务去finetune一个模型,而是使用同一个大模型......
  • 直播系统开发,springboot指定时间触发定时任务
    直播系统开发,springboot指定时间触发定时任务新建测试Demo类执行定时任务 packagecom.task.zhixingshijian;importjava.time.LocalDateTime;importjava.time.temporal.ChronoField;importjava.util.*;/** *@authorwuzhenyong *ClassName:TaskDemo.java *date:2022-......
  • Golang 需要注意的知识点
    云笔记链接地址 go的协程轻量级体现在哪(1)goroutine是轻量级的用户态线程,上下文切换代价小go将goroutine的调度维持在用户态常规线程切换会导致用户态程序代码和内核态操作系统调度程序的切换只涉及PC(程序计数器,标记当前执行的代码的位置)SP(当前执行的函数堆栈栈......
  • Springboot-配置文件
    1.SpringBoot配置文件格式1.properties2.ymlproperties优先级高于yml。自动识别的配置文件:bootstrap.yml和application.yml,bootstrap.yml先于application.yml加载,一般用于系统级别的配置,application.yml一般用于项目级别的配置Springboot官方的配置:https://docs......
  • springBoot 整合 poi 导出带有复杂表格(合并表格)的word文件
    1.Maven依赖见上一篇文章直接贴源码如下:packagecom.mingx.pms.web.system.file;importcn.hutool.core.date.DateUtil;importcom.mingx.pms.constant.SystemInfo;importcom.mingx.pms.entities.workplan.plan.vo.WorkPlanDetailExportVO;importcom.mingx.pms.entities......
  • java常用知识
    提取对象数组里面的某个字段List<String>lastTask=lastTasks.stream().map(HistoricActivityInstance::getActivityId).limit(1).collect(Collectors.toList());对象数组排序notEmptyList.sort(Comparator.comparing......
  • SpringBoot 测试实践 - 3:@MockBean、@SpyBean 、提升测试运行速度、Testcontainer
    编写测试的时候,我们必须保证外部依赖行为一致,也需要模拟一些边界条件,所以我们需要使用Mock来模拟对象的行为。SpringBoot提供了@MockBean和@SpyBean注解,可以方便地将模拟对象与Spring测试相结合,简化测试代码的编写@MockBean@MockBean是SpringBootTest提供的注解,用......
  • js知识点学习01
    js知识点学习011.arguements对象(1)什么是arguements对象?由于JavaScript允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来。(2)怎么使用?arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[......
  • spring和springboot笔试题
    springboot选择题、判断题_西凉辰的博客-CSDN博客Java常见的spring笔试选择题_spring选择题_学亮编程手记的博客-CSDN博客 ......
  • 扩展功能_代码生成器
            ......