【问题标题】:Cannot inject property value to class parameter (@Value annotatnion)无法将属性值注入类参数(@Value 注释)
【发布时间】:2019-09-01 07:44:03
【问题描述】:

我正在学习 Spring Boot,我可能有非常简单的问题,但对我来说还不够清楚。我在使用 @Value 注释时遇到了一些问题——我想知道为什么 apprication 属性不能注入到类参数中。

我使用 Spring Initializr 准备了一些非常基本的项目,并在我的“application.properties”资源中添加了一个属性。此外,我创建了两个额外的类:“YellowCar”(工作正常)和“RedCar”(不起作用 - 无法正确注入参数)。

“application.properties”文件:

car.age=15

我的应用程序的主类:

package com.example.helper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;

@SpringBootApplication
public class HelperApplication implements CommandLineRunner {

    @Autowired
    private Environment env;

    public static void main(String[] args) {
        SpringApplication.run(HelperApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println (new RedCar(env));
        System.out.println (new YellowCar());
    }

}

RedCar 是通过将环境变量传递给构造函数来构建的:

package com.example.helper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
public class RedCar {

    private int age;

    @Autowired
    public RedCar (Environment env) {
        this.age = new Integer(env.getRequiredProperty("car.age")).intValue();
    }

    @Override
    public String toString() {
        return "Car [age=" + age + "]";
    }

}

YellowCar 是在没有将环境变量传递给构造函数的情况下构建的,而是使用 @Value 注释:

package com.example.helper;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class YellowCar {

    @Value("${car.age}")
    private int age;

    @Override
    public String toString() {
        return "YellowCar [age=" + age + "]";
    }

}

这是程序输出:

Car [age=15]
YellowCar [age=0]

如您所见,YellowCar 的年龄未正确注入(等于 0)。

我的目标:我不想到处都将 Environment 对象传递给其他类的构造函数……我想改用 @Value annotatnio。有人可以解释一下吗: 1)为什么我的代码不起作用? 2) 应如何更新此代码以获得以下输出?

Car [age=15]
YellowCar [age=15]

谢谢!

【问题讨论】:

    标签: spring properties annotations autowired application.properties


    【解决方案1】:

    发生这种情况是因为您直接实例化了YellowCar。为了使事情正常工作,@Autowire YellowCarHelperApplication 内并像这样使用这个注入的实例(未测试):

    @Autowired
    private YellowCar yellowCar;
    
    public static void main(String[] args) {
        SpringApplication.run(HelperApplication.class, args);
    }
    
    @Override
    public void run(String... args) throws Exception {
        System.out.println (new RedCar(env));
        System.out.println (yellowCar);
    }
    

    说明:

    当你使用 new 创建类时,Spring 对这个新实例一无所知,因此它不能注入任何东西。但是当通过 Spring 基础设施创建实例时(我在这里尽量不使用很多俚语),它将注入所有字段:当您使用 @Component 注释标记类或使用 @Bean 注释创建方法时,您告诉Spring,你希望它成为一个 Bean。在应用程序启动时,spring 创建这个 bean 的实例 - 默认情况下每个上下文只有一个实例 - 并将这个实例注入到所有其他请求的 bean 中。在这种情况下,这个实例正在由 spring 基础设施(执行它的确切类 - AutowiredAnnotationBeanPostProcessor)处理,并且其他 bean 的实例将被注入到我们的 bean 中。

    UPD:你可以用RedCar做同样的事情:

    @Autowired
    private YellowCar yellowCar;
    
    @Autowired
    private RedCar redCar;
    
    public static void main(String[] args) {
        SpringApplication.run(HelperApplication.class, args);
    }
    
    @Override
    public void run(String... args) throws Exception {
        System.out.println (redCar);
        System.out.println (yellowCar);
    }
    

    【讨论】:

    • 感谢@Flame239 的出色而清晰的解释!祝你有美好的一天!
    • 标记(我希望:)))。再次感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-22
    • 2019-04-30
    • 2012-09-26
    • 2015-07-03
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    相关资源
    最近更新 更多