繁体   English   中英

Spring Boot - @Value 返回 null

[英]Spring Boot - @Value returning null

我正在尝试使用 @Value 注释并从属性文件中自动填充我的变量,但没有运气。 值未设置且为空。

任务服务.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;
    }
}

事件处理程序

@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);
        }
    }
}

字段注入发生在对象被构造之后。
https://stackoverflow.com/a/6336013/1544715
只需通过构造函数注入aatestTemplateBuilder
一般来说,你应该避免字段注入,或者至少尝试并且每个类只使用一种类型的注入。

首先检查您的属性文件是否已加载,通常在输出日志的开头,您应该看到属性文件的名称。

然后在您的配置文件之一中配置以下 bean(如果尚未完成)。 这个 bean 解析 @Value 中的 '${}'。

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

然后使用您正在做的方式,它应该解析该属性。并确保实际加载了TaskService bean(组件扫描包应包含此类)

虽然我通常使用上述方式,但还有另一种方式,您可能需要检查(仅供参考,上面应该可行)

 @Autowired
 private Environment env

然后在需要的地方使用属性

 env.getRequiredProperty(“some.property”)

很多时候的问题是在构造函数完成之后字段注入也完成了。 这意味着您只能在此之后访问使用 @Value 注入的值。 如果将getAA()方法添加到 TaskService:

public String getAA() {
 return aa;
}

并且这个方法被调用,aa的值不为null,因为之前执行了构造函数并且@Value("${a}")的字段注入设置了值。

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

您的代码无法工作,因为 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

像这样修复它:

@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();
    }

这是因为您没有定义带有aa作为参数的构造函数,该类也没有 setter,因此无法注入它。

请阅读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