无论是Spring还是SpringBoot开发中,PostConstruct注解的使用频率还是比较高的,通常用于Bean初始化完成的一些动作。
在项目代码中,会将配置从配置中心中读取,然后初始化到指定的Bean中。其他需要动态获取配置的地方,直接依赖注入这个Bean即可。
示例代码如下:
ApplicationConfig
动态配置所在的类,主要是属性。
1 | java复制代码@Configuration |
ApplicationConfigLoadService
从远程配置中心中获取配置信息,主要依赖PostConstruct方法。
1 | java复制代码@Service |
ApplicationClientFactory
使用ApplicationConfig,基于配置信息,在类初始化完成后,做一些动作。
1 | java复制代码@Component |
备注:
- 主要的类中,提供了一个无参的构造方法,以及一个使用了@PostConstructor注解的初始化方法,主要用于看一下执行顺序。
- 代码说明
- ApplicationConfigLoadService 的初始化方法中加载配置
- ApplicationConfig的setter方法完成配置初始化
- ApplicationClientFactory依赖ApplicationConfig中的属性完成一些初始化工作。
将上述代码执行一下,并查看日志。
1 | properties复制代码2021-06-06 15:38:28.591 INFO 2790 --- [ main] c.y.m.c.ApplicationClientFactory : ApplicationClientFactory constructor execute |
可以看到ApplicationClientFactory的构造方法先被执行,然后由于依赖ApplicationConfig类,所以ApplicationConfig的构造方法和标识了PostConstruct注解的方法被执行,然后才会执行ApplicationClientFactory自己的postConstruct方法。
但是从日志中可以看出,此时由于ApplicationConfigLoadService还没被加载,所以读取到的配置都是空的。
尝试的解决方案
方案1:是可以采用DependsOn指定Bean的加载顺序。
修改代码如下:
value即为依赖Bean的名称。
1 | java复制代码@DependsOn(value = {"applicationConfigLoadService"}) |
1
2
3
4
5
6 > vbnet复制代码Beans on which the current bean depends. Any beans specified are guaranteed to be
> created by the container before this bean. Used infrequently in cases where a bean
> does not explicitly depend on another through properties or constructor arguments,
> but rather depends on the side effects of another bean's initialization.
>
>
从JDK文档可以看出,DependsOn注解主要的使用场景是当前Bean没有显示通过属性或者构造参数依赖另外一个Bean,但是却要依赖另外一个Bean的一些初始化动作。
在上述代码示例中,通过添加DependsOn注解,可以解决问题。
1 | properties复制代码2021-06-06 16:36:59.944 INFO 3688 --- [ main] c.y.m.c.ApplicationConfigLoadService : ApplicationConfigLoadService constructor execute |
方案2: 显示通过@Resource或者@Autowired注入待依赖的Bean
在DependsOn的JDK代码中也可以看到,通过显示依赖可以解决问题。通过签名日志可以看出,当显示依赖注入某个Bean时,被注入Bean会依次执行对应的构造函数以及@PostConstructor注解的初始化方法。
1 | java复制代码public class ApplicationClientFactory { |
执行结果
1 | properties复制代码2021-06-06 16:08:17.458 INFO 3286 --- [ main] c.y.m.c.ApplicationClientFactory : ApplicationClientFactory constructor execute |
此时可以看到在ApplicationClientFactory的postConstruc中,依赖的ApplicationConfig是有对应属性值的。
但是,此处会存在一个风险问题,由于applicationConfigLoadService这个变量在当前类中并未实际使用,仅仅是为了依赖其postConstruct方法。对于后续维护的同学,很有可能无意将其移除。
本文转载自: 掘金