• 请不要在回答技术问题时复制粘贴 AI 生成的内容
NoKey
V2EX  ›  程序员

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

  •  
  •   NoKey · Sep 29, 2022 · 4072 views
    This topic created in 1498 days ago, the information mentioned may be changed or developed.

    整体基于 springboot 框架

    有一个 bean

    @Component
    public class DemoParam {
        private int flag;
    }
    

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

    我想到的方法有:

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

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

    请大家指点,谢谢

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

    ---

    可以统一放到 @Configuration 里面。

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

    ---

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

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

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

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

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

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