V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NoKey
V2EX  ›  程序员

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

  •  
  •   NoKey · 68 天前 · 2432 次点击
    这是一个创建于 68 天前的主题,其中的信息可能已经有所发展或是发生改变。

    整体基于 springboot 框架

    有一个 bean

    @Component
    public class DemoParam {
        private int flag;
    }
    

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

    我想到的方法有:

    • 在构造方法中初始化 flag
    • 写一个方法,用@PostConstruct注解

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

    请大家指点,谢谢

    20 条回复    2022-09-30 14:30:32 +08:00
    bcllemon
        1
    bcllemon  
       68 天前
    用用 @Value 注解,直接配置?
    JYii
        2
    JYii  
       68 天前
    实现 ApplicationRunner 方法,@order 自定义顺序
    wolfie
        3
    wolfie  
       68 天前
    放在 @PostConstruct 好管理。

    ---

    可以统一放到 @Configuration 里面。

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

    ---

    或者 去掉 @Component ,手动创建 @Bean
    yazinnnn
        4
    yazinnnn  
       68 天前
    private val flag by lazy {repo.getFlag()}

    能用 kotlin 的话,可以直接 by lazy
    NoKey
        5
    NoKey  
    OP
       68 天前
    @bcllemon 需要即时从数据库获取
    NoKey
        6
    NoKey  
    OP
       68 天前
    @JYii 意思是,在 springboot 启动的过程,去给 DemoParam 这个 bean ,set 一个值进去么?谢谢
    moshiyeap100
        7
    moshiyeap100  
       68 天前
    2 楼的是一个不错的方法,个人觉得比 @PostConstruct 更适合一点。

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

    这两个 Runner 会在容器启动完成后自动执行,而且可以按顺序启动。
    zilongzixue
        8
    zilongzixue  
       68 天前   ❤️ 1
    @PostConstruct 就行了,不用搞那么多花里胡哨的东西
    nothingistrue
        9
    nothingistrue  
       68 天前
    有一个比较重的方式,如果只是初始化一两个全局变量的话没必要,如果是参与系统架构调整的话,可以考虑。

    定义并注册 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
        10
    wellerman  
       68 天前
    既然都放数据库了,肯定还有更改的时候。那参考一下 ruoyi-vue-pro ,把它那个简化后的 apollo client 移植过来,一劳永逸。
    dddd1919
        11
    dddd1919  
       68 天前
    如果这种初始化的变量后面会越来越多的话,建议使用懒加载的方式避免服务启动时间越来越长

    第一种可以在类里定义属性然后定义 getter 方法,在方法中
    ```java
    if (null == flag) {
    flag = 从数据库读取
    }
    return flag
    ```
    lonenol
        12
    lonenol  
       68 天前
    感觉你这个需求不太对。。如果是配置还是放在配置文件里更好一点。。
    这种做法可能需要考虑一下性能和启动速度,如果懒加载了可能需要考虑第一次访问会不会造成拥堵
    FanError
        13
    FanError  
       68 天前
    @zilongzixue
    @wolfie
    放在 ApplicationRunner 里比 PostConstruct 好,如果是微服务下,feign 远程调用可能还没初始化完成。
    aptupdate
        14
    aptupdate  
       68 天前
    @lonenol op 的需求是从数据库里获取值,不过也是需要考虑启动速度和拥堵的问题。
    如果只有一个参数的话无所谓,参数多的话考虑 Apollo 或者 nacos 这种配置管理组件?
    watzds
        15
    watzds  
       68 天前
    读数据库干嘛搞一个变量呢,直接调用方法呗
    zliea
        16
    zliea  
       68 天前
    我习惯性用 initializeBean
    Chinsung
        17
    Chinsung  
       68 天前
    不如放在配置中心里去,这样只会越写越复杂
    voydomnvd
        18
    voydomnvd  
       68 天前 via Android
    首先单体应用用 ApplicationRunner 就行
    如果是微服务的情况下,配置中心里好一点,有值需要变动的话再加上 @RefreshScope 呗,要是经常变就 Redis 或 DB 了
    fuxinya
        19
    fuxinya  
       68 天前 via Android
    CommandLineRunner
    vishun
        20
    vishun  
       67 天前
    如果是只初始化一下的话,放数据库或配置文件都没什么影响。
    但放到数据库更多的是会修改,此时就会涉及到线程安全问题或者是 bean 的热更新问题。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2014 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 16:57 · PVG 00:57 · LAX 08:57 · JFK 11:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.