新手请教, springboot 框架下,哪种初始化变量的方法更好

2022-09-29 11:36:53 +08:00
 NoKey

整体基于 springboot 框架

有一个 bean

@Component
public class DemoParam {
    private int flag;
}

flag需要在初始化阶段从数据库获取值

我想到的方法有:

哪种方法更好呢,或者有没有更好、更优雅的方法

请大家指点,谢谢

2842 次点击
所在节点    程序员
20 条回复
bcllemon
2022-09-29 11:38:42 +08:00
用用 @Value 注解,直接配置?
JYii
2022-09-29 11:42:00 +08:00
实现 ApplicationRunner 方法,@order 自定义顺序
wolfie
2022-09-29 11:47:15 +08:00
放在 @PostConstruct 好管理。

---

可以统一放到 @Configuration 里面。

@Bean
public SmartInitializingSingleton fooBarConfig(@Autowired DemoParam demoParam, @Autowired FooBarMapper fooBarMapper) {
return () -> {
demoParam.setFlag(fooBarMapper.getConfig());
};
}

---

或者 去掉 @Component ,手动创建 @Bean
yazinnnn
2022-09-29 11:51:48 +08:00
private val flag by lazy {repo.getFlag()}

能用 kotlin 的话,可以直接 by lazy
NoKey
2022-09-29 11:56:34 +08:00
@bcllemon 需要即时从数据库获取
NoKey
2022-09-29 11:58:09 +08:00
@JYii 意思是,在 springboot 启动的过程,去给 DemoParam 这个 bean ,set 一个值进去么?谢谢
moshiyeap100
2022-09-29 11:59:28 +08:00
2 楼的是一个不错的方法,个人觉得比 @PostConstruct 更适合一点。

可以自行实现 CommandLineRunner 或者 ApplicationRunner ,集中初始化一些需要读库的配置对象。

这两个 Runner 会在容器启动完成后自动执行,而且可以按顺序启动。
zilongzixue
2022-09-29 13:03:40 +08:00
@PostConstruct 就行了,不用搞那么多花里胡哨的东西
nothingistrue
2022-09-29 14:08:47 +08:00
有一个比较重的方式,如果只是初始化一两个全局变量的话没必要,如果是参与系统架构调整的话,可以考虑。

定义并注册 Spring 容器启动事件监听,再监听中处理,可以一个监听处理多个场景的初始化。
定义监听类:public class ApplicationContextRefreshed implements ApplicationListener<ContextRefreshedEvent>
注册监听:启动类修改成如下,
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.addListeners(new ApplicationContextRefreshed());
springApplication.run(args);
}



还有一种更简单的配置方式,定义下面这个构造器即可:
@Autowird
public DemoParam(@Autowird DaoOrJpaRepistory daoOrRepo ){
flag = daoOrRepo.xxxx;
}
wellerman
2022-09-29 14:26:58 +08:00
既然都放数据库了,肯定还有更改的时候。那参考一下 ruoyi-vue-pro ,把它那个简化后的 apollo client 移植过来,一劳永逸。
dddd1919
2022-09-29 14:50:38 +08:00
如果这种初始化的变量后面会越来越多的话,建议使用懒加载的方式避免服务启动时间越来越长

第一种可以在类里定义属性然后定义 getter 方法,在方法中
```java
if (null == flag) {
flag = 从数据库读取
}
return flag
```
lonenol
2022-09-29 14:58:18 +08:00
感觉你这个需求不太对。。如果是配置还是放在配置文件里更好一点。。
这种做法可能需要考虑一下性能和启动速度,如果懒加载了可能需要考虑第一次访问会不会造成拥堵
FanError
2022-09-29 15:08:50 +08:00
@zilongzixue
@wolfie
放在 ApplicationRunner 里比 PostConstruct 好,如果是微服务下,feign 远程调用可能还没初始化完成。
aptupdate
2022-09-29 15:12:53 +08:00
@lonenol op 的需求是从数据库里获取值,不过也是需要考虑启动速度和拥堵的问题。
如果只有一个参数的话无所谓,参数多的话考虑 Apollo 或者 nacos 这种配置管理组件?
watzds
2022-09-29 15:18:00 +08:00
读数据库干嘛搞一个变量呢,直接调用方法呗
zliea
2022-09-29 15:42:49 +08:00
我习惯性用 initializeBean
Chinsung
2022-09-29 16:15:20 +08:00
不如放在配置中心里去,这样只会越写越复杂
voydomnvd
2022-09-29 20:11:18 +08:00
首先单体应用用 ApplicationRunner 就行
如果是微服务的情况下,配置中心里好一点,有值需要变动的话再加上 @RefreshScope 呗,要是经常变就 Redis 或 DB 了
fuxinya
2022-09-29 20:14:28 +08:00
CommandLineRunner
vishun
2022-09-30 14:30:32 +08:00
如果是只初始化一下的话,放数据库或配置文件都没什么影响。
但放到数据库更多的是会修改,此时就会涉及到线程安全问题或者是 bean 的热更新问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/883764

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX