注释@Value在Spring Boot中不能正常工作?

时间:2019-04-03 05:34:20

标签: java spring spring-boot

上下文:

我处理带有@Scheduled批注的报表,并且当从Component属性调用Service的属性@Value初始化时,即使它实际上存在于.properties中,也无法打印该报表在@PostConstruct中。

说明:

ReportProcessor界面和InventoryReportProcessor实现:

@FunctionalInterface
interface ReportProcessor {
    public void process(OutputStream outputStream);
}

@Component
public class InventoryReportProcessor implement ReportProcessor {

    @Value("${reportGenerator.path}")
    private String destinationFileToSave;

    /*
    @PostConstruct
    public void init() {
        System.out.println(destinationFileToSave);
    }
    */

    @Override
    public Map<String, Long> process(ByteArrayOutputStream outputStream) throws IOException {
        System.out.println(destinationFileToSave);

        // Some data processing in here
        return null;
    }
}

我从

使用它
@Service
public class ReportService {
    @Value("${mws.appVersion}")
    private String appVersion;

    /* Other initialization and public API methods*/

    @Scheduled(cron = "*/10 * * * * *")
    public void processReport() {
        InventoryReportProcessor reportProcessor = new InventoryReportProcessor();
        Map<String, Long> skus = reportProcessor.process(new ByteArrayOutputStream());
    }
}

我的困惑来自以下事实:@Value中的Service可以正常工作,但是在@Component中它返回null,除非在@PostConstruct中调用。另外,如果调用@PostConstruct,则该值在其余的类代码中仍为null

我发现了类似的Q&A,并且在Srping docs进行了研究,但到目前为止,还没有一个单一的想法为什么它会以这种方式起作用,什么可以作为解决方案?

3 个答案:

答案 0 :(得分:2)

您需要自动装配组件,以使Spring应用程序知道该组件。

@Service
public class ReportService {
    @Value("${mws.appVersion}")
    private String appVersion;

    /* Other initialization and public API methods*/
    @Autowired
    private ReportProcessor reportProcessor;

    @Scheduled(cron = "*/10 * * * * *")
    public void processReport() {
        //InventoryReportProcessor reportProcessor = new InventoryReportProcessor();
        Map<String, Long> skus = reportProcessor.process(new ByteArrayOutputStream());
    }
}

答案 1 :(得分:2)

在构造对象之后进行字段注入,因为显然容器无法设置不存在的属性。

当时的System.out.println(destinationFileToSave);触发器值未注入;

如果您希望它能正常工作,请尝试类似的操作

@Autowired
InventoryReportProcessor  pross;

pross.process(ByteArrayOutputStream outputStream);

@PostConstruct在对象创建后被调用时起作用。

答案 2 :(得分:0)

Spring只会在已知的bean上解析@Value注释。您使用的代码会在Spring范围之外创建该类的实例,因此Spring对此不会采取任何措施。 您可以做的一件事是显式创建实例或使用Autowire:

@Autowired
    private ReportProcessor reportProcessor;

tl:dr 如果正确配置了应用程序上下文,则@Value不能为 null ,因为这将停止正确启动应用程序。 / p>

更改您的代码

@Value("${reportGenerator.path}")
private String destinationFileToSave;

@Value("${reportGenerator.path}")
public void setDestinationFileToSave(String destinationFileToSave) {
    SendMessageController.destinationFileToSave = destinationFileToSave;
}