Spring启动时实现初始化的几种方式

编程入门 行业动态 更新时间:2024-10-21 06:17:55

Spring启动时实现初始化的<a href=https://www.elefans.com/category/jswz/34/1769370.html style=几种方式"/>

Spring启动时实现初始化的几种方式

准确的说是spring容器实例化完成后,几种初始化的方式。为什么这么说呢?下看面示例:

@Slf4j
@Component
public class InitBeanDemo {@Autowiredprivate 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;@Autowiredpublic 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 {@Autowiredprivate Environment env;@PostConstructpublic 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 {@Autowiredprivate Environment env;@Overridepublic 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 {@Autowiredprivate 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>{@Autowiredprivate Environment env;@Overridepublic 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 {@Autowiredprivate Environment env;@EventListenerpublic 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 {@Autowiredprivate Environment env;@Overridepublic 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 {@Autowiredprivate Environment env;@Overridepublic 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]

也即 整篇文章整理的先后顺序。



更多推荐

Spring启动时实现初始化的几种方式

本文发布于:2024-03-23 16:45:02,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1740482.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:几种   初始化   启动时   方式   Spring

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!