Spring启动时实现初始化有哪些方式?
作者:pbxs 发布时间:2023-09-20 18:25:57
一、Spring启动时实现初始化的几种方式
准确的说是spring容器实例化完成后,几种初始化的方式。为什么这么说呢?下看面示例:
@Slf4j
@Component
public class InitBeanDemo {
@Autowired
private Environment env;
public InitBeanDemo() {
log.info("DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
示例是在bean的构造方法里做一些初始化的工作,示例比较简单只做了日志打印。是理想很丰满,现实很骨感,报错了:Constructor threw exception; nested exception is java.lang.NullPointerException。
原因是,Environment尚未初始化完成。
接下来我们来探索一下 有哪些初始化方式能满足上面示例的需求。
二、构造方法里初始化
可以正常运行,在所有初始化方式里执行时机最早。原理是在InitBeanDemo实例化前就实例化了Environment。
@Component
public class InitBeanDemo {
private final Environment env;
@Autowired
public InitBeanDemo (Environment environment) {
this.env = environment;
log.info("Constructor DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("Constructor ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
}
三、常规三件套
常规三件套:@PostConstruct、InitializingBean、initMethod。 如果你愿意的话,三种方式可以在同一个Bean下同时使用,执行的优先级@PostConstruct > InitializingBean > initMethod。
@PostConstruct注解
在一个可以被扫描到Bean里,添加一个public void xxx()方法并加上@PostConstruct注解,方法里编写需要初始化的逻辑。
同一个应用程序里可以有多个@PostConstruct注解,同一个Bean里也可以有多个@PostConstruct注解。
@Slf4j
@Component
public class InitBeanDemo {
@Autowired
private Environment env;
@PostConstruct
public void init() {
log.info("@PostConstruct DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("@PostConstruct ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
实现InitializingBean接口
实现InitializingBean接口,在afterPropertiesSet() 方法里编写需要初始化的逻辑。
同一个应用程序里可以有多个实现InitializingBean接口的类,执行时机会按类名的自然顺序排序。
@Slf4j
@Component
public class InitBeanDemo implements InitializingBean {
@Autowired
private Environment env;
@Override
public void afterPropertiesSet() throws Exception {
log.info("InitializingBean DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("InitializingBean ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
}
指定Bean的initMethod方法
使用@Bean注解的initMethod属性可用于Bean的初始化后执行的方法。initMethod必须是public void 的无参构造方法。
@Slf4j
public class InitBeanDemo implements InitializingBean {
@Autowired
private Environment env;
public void initMethod() {
log.info("initMethod DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("initMethod ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
@Configuration
public class InitBeanConfig {
@Bean(initMethod="initMethod")
public InitBeanDemo initBeanDemo () {
return new InitBeanDemo();
}
}
等同于 在XML 配置中的init-method属性:
<bean id="initBeanDemo" class="com.xxx.InitBeanDemo" init-method="initMethod"></bean>
四、自定义ApplicationListener监听
两种方式,一种实现接口,另一种使用注解。
实现ApplicationListener接口
监听ContextRefreshedEvent事件。
@Slf4j
@Component
public class InitBeanDemo implements ApplicationListener<ContextRefreshedEvent>{
@Autowired
private Environment env;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
log.info("ApplicationListener DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("ApplicationListener ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
}
@EventListener注释
方法参数里指定ContextRefreshedEvent事件。
@Slf4j
@Component
public class InitBeanDemo {
@Autowired
private Environment env;
@EventListener
public void onApplicationEvent2(ContextRefreshedEvent event) {
log.info("@EventListener DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("@EventListener ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
}
五、Spring Boot提供的初始化接口
ApplicationRunner接口
@Slf4j
@Component
public class InitBeanDemo implements ApplicationRunner {
@Autowired
private Environment env;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("ApplicationRunner: {}", args);
log.info("ApplicationRunner: {}", args.getOptionNames());
log.info("ApplicationRunner DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("ApplicationRunner ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
}
CommandLineRunner接口
可以在同一个应用程序上下文中定义多个CommandLineRunner bean,并且可以使用@Ordered接口或@Order注释进行排序。
@Slf4j
@Component
public class InitBeanDemo implements CommandLineRunner {
@Autowired
private Environment env;
@Override
public void run(String... args) throws Exception {
log.info("CommandLineRunner: {}", args);
log.info("CommandLineRunner DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
log.info("CommandLineRunner ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
}
}
在同一个Bean里使用以上初始化方式的执行先后顺序
在同一个Bean里使用以上初始化方式,运行的日志片段:
2021-06-07 11:24:41|INFO |main|c.c.s.s.t.ConstructorInitDemo|Constructor DefaultProfiles: [default]
2021-06-07 11:24:41|INFO |main|c.c.s.s.t.ConstructorInitDemo|Constructor ActiveProfiles: [sit]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|@PostConstruct DefaultProfiles: [default]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|@PostConstruct ActiveProfiles: [sit]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|InitializingBean DefaultProfiles: [default]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|InitializingBean ActiveProfiles: [sit]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|initMethod DefaultProfiles: [default]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|initMethod ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|@EventListener DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|@EventListener ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationListener DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationListener ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner: org.springframework.boot.DefaultApplicationArguments@68bef3df
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner: []
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|CommandLineRunner: {}
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|CommandLineRunner DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|CommandLineRunner ActiveProfiles: [sit]
也即 整篇文章整理的先后顺序。
来源:https://blog.csdn.net/WLQ0621/article/details/117661645


猜你喜欢
- 本文实例为大家分享了Android使用GridView实现横向滚动效果的具体代码,供大家参考,具体内容如下第一次做横向滑动,看了一些列子,基
- 1.要求输入10个整数,从大到小排序输出输入:2 0 3 -4 8 9 5 1 7 6输出:9 8 7 6 5 3 2 1 0 -4解决方法
- springboot 取消starter的自动注入starer是spring boot中一个很重要的概念,starter相当于一个模块,它能
- 一、串口连接的打开与关闭串口,即COM口,在.NET中使用 SerialPort 类进行操作。串口开启与关闭,是涉及慢速硬件的IO操作,频繁
- 我就废话不多说了,大家还是直接看代码吧~import java.io.UnsupportedEncodingException;import
- 官方文档 8.0Spring为不同缓存做了一层抽象,这里通过阅读文档以及源码会对使用以及原理做一些学习笔记。1.简介
- 我的接口是这样的:TestCase测试Impl类的方法没有问题,但是Swgger和前端调用接口就会报404错误:在网上查了很多资料,都说是地
- 前言本文主要给大家介绍了关于Spring Boot优化内嵌Tomcat的相关内容,分享出来供大家参考学习,下面话不多说了,来一看看详细的介绍
- java 线程池详解什么是线程池?提供一组线程资源用来复用线程资源的一个池子为什么要用线程池?线程的资源是有限的,当处理一组业务的时候,我们
- 前言 因为自己在做的一个小软件里面需要用到从A-Z排序的ListView,所以自然而然的想到了微信的联系人,我想要的就是那样的效果。本来没
- 本文实例讲述了C#基于UDP进行异步通信的方法。分享给大家供大家参考。具体如下:服务器端:using System;using System
- 前言周六在公司写Reactor模型,一女同事问我为啥都2023年了还在学习Reactor模型呀,我问她为啥快30的年纪了,周六还在公司看我写
- 前言在Android开发中,View一直是Android开发人员的一块心病,一方面想要进阶,一方面又害怕进阶,可以说Android的View
- 正在尝试分配更低的访问权限?在进行Java编程时会给我们报出如下提示怎么办?这里我们将给大家介绍详细的解决方法。首先,查看,控制台给出的提示
- 概述使用this()或target()可绑定被代理对象实例,在通过类实例名绑定对象时,还依然具有原来连接点匹配的功能,只不过类名是通过增强方
- 1.创建一个带Mesh的物体Unity中的网格作为组件不能脱离物体单独存在新建脚本CreateMeshpublic class Create
- 本文实例讲述了C#中Socket通信用法。分享给大家供大家参考。具体如下:一、UDP方式:服务器端代码:static void Main(s
- 一、概述今天给大家带来SurfaceView的一个实战案例,话说自定义View也是各种写,一直没有写过SurfaceView,这个玩意是什么
- 前言以前用到要对数字格式的地方,都是直接到网上搜一下。拿过来能用就行。因为平时用的不多。但是最近的项目对这个用的多了。网上拿来的不够用了。自
- import java.io.*;/** * Created by tang on 14-3-1. */public c