有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java注释@Value在Spring Boot中无法正常工作?

上下文:

我处理带有@Scheduled注释的报告,并且当从Service属性调用Component时,没有使用@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());
    }
}

我的困惑来自这样一个事实,即@Valuein Service工作正常,但在@Component中它返回null,除非调用@PostConstruct。此外,如果调用@PostConstruct,则该值仍然保留在类代码的其余部分中

我发现了类似的Q&A,我在Srping docs做了研究,但到目前为止,还没有一个单一的想法,为什么它会以这种方式工作,什么是解决方案


共 (3) 个答案

  1. # 1 楼答案

    Spring将只解析它知道的bean上的@Value注释。您使用的代码在Spring的作用域之外创建了一个类的实例,因此Spring不会对它做任何处理。 可以做的一件事是显式创建实例或使用Autowire:

    @Autowired
        private ReportProcessor reportProcessor;
    

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

    从更改代码

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

    @Value("${reportGenerator.path}")
    public void setDestinationFileToSave(String destinationFileToSave) {
        SendMessageController.destinationFileToSave = destinationFileToSave;
    }
    
  2. # 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());
        }
    }
    
  3. # 3 楼答案

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

    在时间系统中。出来println(destinationfileosave);触发器值未被注入

    如果你想看到它的工作尝试这样的东西

    @Autowired
    InventoryReportProcessor  pross;
    
    pross.process(ByteArrayOutputStream outputStream);
    

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