浅谈SpringBoot中的Bean初始化方法 @PostConstruct

网友投稿 1254 2022-11-19

浅谈SpringBoot中的Bean初始化方法 @PostConstruct

浅谈SpringBoot中的Bean初始化方法 @PostConstruct

目录注解说明代码示例注解示例错误示例正确示例SpringBoot @PostConstruct虽好,也要慎用1 问题的产生2 案例模拟3 总结

注解说明

使用注解: @PostConstruct

效果:在Bean初始化之后(构造方法和@Autowired之后)执行指定操作。经常用在将构造方法中的动作延迟。

备注:Bean初始化时候的执行顺序ZICCcIQxf: 构造方法 -> @Autowired -> @PostConstruct

代码示例

注解示例

@Component

public class PostConstructTest1 {

@Autowired

PostConstructTest2 postConstructTest2;

public PostConstructTest1() {

// postConstructTest2.hello();

}

@PostConstruct

public void init() {

// some init function

}

}

在Bean的初始化操作中,有时候会遇到调用其他Bean的时候报空指针错误。这时候就可以将调用另一个Bean的方法这个操作放到@PostConstruct注解的方法中,将其延迟执行。

错误示例

@Component

public class PostConstructTest1 {

@Autowired

PostConstructTest2 postConstructTest2;

public PostConstructTest1() {

postConstructTest2.hello();

}

}

@Component

public class PostConstructTest2 {

public void hello() {

System.out.println("hello, i am PostConstructTest2");

}

}

正确示例

@Component

public class PostConstructTest1 {

@Autowired

PostConstructTest2 postConstructTest2;

public PostConstructTest1() {

postConstructTest2.hello();

}

}

@Component

public class PostConstructTest1 {

@Autowired

PostConstructTest2 postConstructTest2;

public PostConstructTest1() {

// postConstructTest2.hello();

}

@PostConstruct

public http://void init() {

postConstructTest2.hello();

}

}

SpringBoot @PostConstruct虽好,也要慎用

做过SpringBoot开发的话,肯定对@PostConstruct比较熟悉。在一个Bean组件中,标记了@PostConstruct的方法会在Bean构造完成后自动执行方法的逻辑。

1 问题的产生

先说下SpringBoot中Bean的加载过程,简单点说就是SpringBoot会把标记了Bean相关注解(例如@Component、@Service、@Repository等)的类或接口自动初始化全局的单一实例,如果标记了初始化顺序会按照用户标记的顺序,否则按照默认顺序初始化。在初始化的过程中,执行完一个Bean的构造方法后会执行该Bean的@PostConstruct方法(如果有),然后初始化下一个Bean。

那么: 如果@PostConstruct方法内的逻辑处理时间较长,就会增加SpringBoot应用初始化Bean的时间,进而增加应用启动的时间。因为只有在Bean初始化完成后,SpringBoot应用才会打开端口提供服务,所以在此之前,应用不可访问。

2 案例模拟

为了模拟上面说的情况,在SpringBoot项目中建两个组件类ComponentOne和ComponentTwo。耗时的初始化逻辑放在ComponentOne中,并设置ComponentOne的初始化顺序在ComponentTwo之前。完整代码如下:

@Component

@Order(Ordered.HIGHEST_PRECEDENCE)

public class ComponentOne {

private Logger logger = LoggerFactory.getLogger(this.getClass());

public ComponentOne() {

this.logger.info("ComponentOne 初始化完成");

}

@PostConstruct

public void init() {

this.logger.info("ComponentOne 模拟耗时逻辑开始");

try {

//这里休眠5秒模拟耗时逻辑

ZICCcIQxf Thread.sleep(1000 * 5);

} catch (InterruptedException e) {

logger.info("模拟逻辑耗时失败", e);

}

this.logger.info("ComponentOne 模拟耗时逻辑完成");

}

}

@Component

@Order(Ordered.HIGHEST_PRECEDENCE + 1)

public class ComponentTwo {

private Logger logger = LoggerFactory.getLogger(this.getClass());

public ComponentTwo() {

this.logger.info("ComponentTwo 初始化完成");

}

@PostConstruct

http:// public void init() {

this.logger.info("ComponentTwo 初始化完成后处理");

}

}

启动应用,初始化部分日志如下:

3 总结

所以,如果应用有一些初始化操作,有以下几点建议:

轻量的逻辑可放在Bean的@PostConstruct方法中

耗时长的逻辑如果放在@PostConstruct方法中,可使用独立线程执行

初始化操作放在CommandLineRunner或ApplicationRunner的实现组件中

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springboot实现pdf里面插入图片
下一篇:C# 通过Dynamic访问System.Text.Json对象
相关文章

 发表评论

暂时没有评论,来抢沙发吧~