【问题标题】:Annotation @Value doesn't work properly in Spring Boot?注解@Value 在 Spring Boot 中不能正常工作?
【发布时间】:2019-04-03 05:34:19
【问题描述】:

上下文:

我使用@Scheduled 注释处理报告,当从Service 属性调用Component 时,即使它物理存在于.properties 中并打印在@PostConstruct 中,也没有使用@Value 注释进行初始化。

描述:

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

我的困惑是因为Service 中的@Value 工作正常,但在@Component 中它返回null,除非调用@PostConstruct。此外,如果调用 @PostConstruct,则该值在类代码的其余部分中仍保留为 null

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

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    您需要Autowire组件以使您的 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());
        }
    }
    

    【讨论】:

      【解决方案2】:

      字段注入是在构造对象之后完成的,因为显然容器不能设置不存在的东西的属性。

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

      如果你想看到它工作,试试这样的

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 2021-03-10
          • 1970-01-01
          • 2018-03-03
          • 1970-01-01
          • 1970-01-01
          • 2020-04-03
          • 2013-10-19
          • 1970-01-01
          • 2018-10-25
          相关资源
          最近更新 更多