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

大佬们 请教一下关于 Spring 的 @Value 注解

  •  
  •   max58 · 2022-03-16 17:15:06 +08:00 · 2225 次点击
    这是一个创建于 975 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我目前遇到的情况大概如下:

    class Test{
        @Value("${xxxx}")
        private String a1;
        @Value("${xxxx}")
        private String a2;
        @Value("${xxxx}")
        private String a3;
        
        private Demo demo;
        public Test(){
            demo = Demo.builder(a1,a2,a3);
        }
    }   
    

    a1,a2,a3 是从公司的配置中心拉去的值 现在出现这种情况: 在启动项目加载的时候,只会加载 a1,a2,a3 并不会给赋值 导致注入 demo 的参数都是 null 个人认为 spring 在加载的时候会把对应的值拉取到然后赋予变量 有没有大佬明白,教一下菜鸡。

    个人的解决办法:创建的一个 Config 类 能保证能够拉取到值然后完成注入

    @Configuration
    public class DemoConfig {
    
        @Value("${xxxx}")
        private String a1;
        @Value("${xxxx}")
        private String a2;
        @Value("${xxxx}")
        private String a3;
    
        @Bean
        public Demo bulid() throws MalformedURLException, SignatureException {
            return new Demo.Builder(a1,a2,a3);
        }
    }
    class Test{
     
        @Resource
        private Demo demo;
      
    } 
    
    
    14 条回复    2022-03-16 22:09:05 +08:00
    XhstormR02
        1
    XhstormR02  
       2022-03-16 17:30:19 +08:00 via Android
    Test 类的构造方法在 @Value 注入之前就调用了
    max58
        2
    max58  
    OP
       2022-03-16 17:33:20 +08:00
    @XhstormR02 我之前还试过一种写法 在 成员字符串变量前加 static 和 不在构造方法中创建 直接去 new 也是不行的
    bringyou
        3
    bringyou  
       2022-03-16 17:42:31 +08:00
    可以在 postcontruct (或者 InitializingBean 的 afterPropertiesSet )里面初始化 demo
    xjngbla
        4
    xjngbla  
       2022-03-16 17:43:38 +08:00
    楼主是在 controller 里使用的这个注解么
    Kasumi20
        5
    Kasumi20  
       2022-03-16 17:55:17 +08:00
    为什么 Demo 不去存 Test 的引用
    zzfer
        6
    zzfer  
       2022-03-16 17:58:40 +08:00
    @Value 注解必须再 spring 注解标注后的类(@Configuration,@Controller,@Service 等)才能起作用吧
    BiChengfei
        7
    BiChengfei  
       2022-03-16 18:03:33 +08:00
    @Component
    public class Test {

    private Demo demo;

    public Test(@Value("${demo.a1}") String a1,@Value("${demo.a2}") String a2,@Value("${demo.a3}") String a3){
    demo = Demo.build(a1,a2,a3);
    }

    }
    max58
        8
    max58  
    OP
       2022-03-16 18:03:53 +08:00
    @xjngbla Service 层 是有 @Swevice 这个注解的
    max58
        9
    max58  
    OP
       2022-03-16 18:05:08 +08:00
    @zzfer 是有 @Service 注解的
    max58
        10
    max58  
    OP
       2022-03-16 18:05:43 +08:00
    @BiChengfei 我去试一下
    zzfer
        11
    zzfer  
       2022-03-16 18:05:45 +08:00
    如果你想在静态代码或非 spring 注解标注的类里使用。可以在 demo 里写好 a1 ,a2 ,a3 的 get 方法,通过这样获取
    DemoConfig demoConfig = ApplicationContextHolder.getBean(DemoConfig .class);
    String a1 = demoConfig .getA1();
    ikas
        12
    ikas  
       2022-03-16 18:13:44 +08:00
    bean 的生命周期基础,常用以下几种方案

    1. 使用 @PostConstruct
    2. 实现 InitializingBean 接口
    3. 指定 initMethod 方法,如 @Bean(initMethod = "init")


    如果想看详细,看 spring 文档 Receiving Lifecycle Callbacks 部分
    paradoxs
        13
    paradoxs  
       2022-03-16 18:16:21 +08:00
    如果是需要从配置中心获取值,要用 @PostConstruct
    1194129822
        14
    1194129822  
       2022-03-16 22:09:05 +08:00
    知其然,知其所以然。楼主还停留在使用阶段,建议楼主去了解一下 spring bean 的生命周期,BeanPostProcessor ,InstantiationAwareBeanPostProcessor 。核心生成 bean 的逻辑在 AbstractAutowireCapableBeanFactory.doCreateBean ,大致流程 createBeanInstance->populateBean->initializeBean ,createBeanInstance 就是实例化,populateBean 就是填充属性,set 和字段注入(@Value ,@Autowired..),initializeBean 就是初始化( Aware, @PostConstruct ,InitializingBean..)。所以 initializeBean 阶段的回调都可以读取注入的值。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2848 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:54 · PVG 13:54 · LAX 21:54 · JFK 00:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.