简体   繁体   English

Spring Boot - @Value 返回 null

[英]Spring Boot - @Value returning null

I'm trying to use @Value annotation and auto-populate my variable from the properties file, but with no luck.我正在尝试使用 @Value 注释并从属性文件中自动填充我的变量,但没有运气。 Values are not being set and are null.值未设置且为空。

taskService.java任务服务.java

@Service
public class TaskService {
    @Value("${a}")
    String aa;

    public final RestTemplate restTemplate;

    public TaskService(RestTemplateBuilder restTemplateBuilder){
        System.out.println("----------xxxxxxxxxxx-------------" +aa);
        this.restTemplate = restTemplateBuilder.build();
    }

    public Task getTask(int taskId) throws TaskDoesNotExistException {
        try {
            return this.restTemplate.getForObject("/tasks/{taskId}", Task.class, taskId);
        } catch (HttpClientErrorException e) {
            if(e.getRawStatusCode() == 404)
                throw new TaskDoesNotExistException("Task not found", e);
        }
        return null;
    }
}

eventhandler.java事件处理程序

@Component
@RepositoryEventHandler(Application.class)
public class ApplicationRepositoryEventHandler {

    @Autowired
    TaskService taskService;

    @HandleBeforeCreate
    public void handleApplicationCreate(Application application) throws TaskDoesNotExistException {
        for (Integer taskId: application.getTasks()){
            taskService.getTask(taskId);
        }
    }
}

Field injection occurs after the object is constructed.字段注入发生在对象被构造之后。
See https://stackoverflow.com/a/6336013/1544715https://stackoverflow.com/a/6336013/1544715
Just inject aa via the constructor along with the testTemplateBuilder .只需通过构造函数注入aatestTemplateBuilder
In general you should avoid field injection, or at least try and only use one type of injection per class.一般来说,你应该避免字段注入,或者至少尝试并且每个类只使用一种类型的注入。

First check if your property file is loaded, Normally beginning of your output log, you should see name of the property file.首先检查您的属性文件是否已加载,通常在输出日志的开头,您应该看到属性文件的名称。

And then configure following bean in one of your configuration file, if not already done .然后在您的配置文件之一中配置以下 bean(如果尚未完成)。 This bean resolves '${}' in @Value.这个 bean 解析 @Value 中的 '${}'。

 @Bean
 public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
 return new PropertySourcesPlaceholderConfigurer();
 }

Then use the way you are doing, It should resolve that property.And make sure that, TaskService bean is actually loaded (component scan package should includes this class)然后使用您正在做的方式,它应该解析该属性。并确保实际加载了TaskService bean(组件扫描包应包含此类)

Although i normally use above way, there is another way, you may need to check (just fyi, above should work)虽然我通常使用上述方式,但还有另一种方式,您可能需要检查(仅供参考,上面应该可行)

 @Autowired
 private Environment env

Then use property wherever needed然后在需要的地方使用属性

 env.getRequiredProperty(“some.property”)

Quite often the problem is that the field injection is finished after the constructor has finished.很多时候的问题是在构造函数完成之后字段注入也完成了。 That means you can access the value that was injected with @Value only after that.这意味着您只能在此之后访问使用 @Value 注入的值。 If a method getAA() ist added to TaskService:如果将getAA()方法添加到 TaskService:

public String getAA() {
 return aa;
}

and this method is called, the value of aa is not null, because the constructor was executed before and the field injection of @Value("${a}") set the value.并且这个方法被调用,aa的值不为null,因为之前执行了构造函数并且@Value("${a}")的字段注入设置了值。

 public TaskService(@Value("${a}") String aa, RestTemplateBuilder restTemplateBuilder){
        System.out.println("----------xxxxxxxxxxx-------------" +aa);
        this.restTemplate = restTemplateBuilder.build();
    }

You code can't work because Spring needs to first create instance of class (call the constructor) and THEN inject values to the fields.您的代码无法工作,因为 Spring 需要首先创建类的实例(调用构造函数) ,然后将值注入字段。

public TaskService(RestTemplateBuilder restTemplateBuilder, ){
        System.out.println("----------xxxxxxxxxxx-------------" +aa); // 1
        this.restTemplate = restTemplateBuilder.build();
    }

1) in this moment there is no way Spring can inject value to the fields

Fix it like this:像这样修复它:

@Service
public class TaskService {

    private final String aa;

    private final RestTemplate restTemplate;

    public TaskService(RestTemplateBuilder restTemplateBuilder, @Value("${a}" String aa){
        this.aa = aa;
        System.out.println("----------xxxxxxxxxxx-------------" +this.aa); // 1
        this.restTemplate = restTemplateBuilder.build();
    }

It is because you don't define a constructor with aa as argument, neither does the class have a setter, so there is no way to inject it.这是因为您没有定义带有aa作为参数的构造函数,该类也没有 setter,因此无法注入它。

Please read https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-setter-injection .请阅读https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-setter-injection

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM