【问题标题】:Not able to read values using @Value in application.yaml in Springboot无法在 Spring Boot 的 application.yml 中使用 @Value 读取值
【发布时间】:2020-10-13 18:36:32
【问题描述】:

我正在使用 Spring 启动 - 2.3.3.RELEASE。 application.yaml 中有一些值,我正在尝试使用 @Value 注释将其注入到类中。但由于某种原因,它们没有加载。结果应该是,在 SendPhoneByPhoneNumbers.java 中,我们应该能够从 application.yaml 中读取 notificationServiceURL。

注意-我使用的是工厂和策略模式。该项目将作为库,供其他项目导入和使用Service层暴露的方法。

这里是文件夹结构:https://imgur.com/a/jYr7wyP 我正在尝试通过在 Debug 模式下运行 Demo.java 来进行测试,以查看实际值的样子。

应用程序.yaml

notificationService:
  url: "https://someURL.com"

Demo.java

@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@SpringBootApplication
public class Demo {

    public static void main(String[] args) {

        SpringApplication.run(Demo.class, args);

        String title="Title";
        String message="message";
        List<String> phoneNumbers = new ArrayList<>();
        phoneNumbers.add("333-222-1111");
        PhoneService phoneService = new PhoneService();
        phoneService.sendNotificationByPhoneNumbers(title, message, phoneNumbers);

    }
}

PhoneService.java

@Service
public class PhoneService {

    PhoneServiceImpl notificationServiceImpl = new PhoneServiceImpl();

    public void sendNotificationByPhoneNumbers(String title, String message, List<String> phoneNumbers) {
        notificationServiceImpl.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
    }
}

PhoneServiceImpl.java

@Slf4j
@Component
public class PhoneServiceImpl {

    @Value("${notificationService.url}")
    String url;

    public void sendNotificationByPhoneNumbers(String title, String message, List<String> phoneNumbers) {
        PhoneContext phoneContext = new PhoneContext(new SendPhoneByPhoneNumbers(url));
        phoneContext.notify(title, message, phoneNumbers);
    }

}

PhoneContext.java

public class PhoneContext {

    private PhoneStrategy phoneStrategy;

    public PhoneContext(PhoneStrategy phoneStrategy){
        this.phoneStrategy = phoneStrategy;
    }

    public void notify(String title, String message, List<String> employees){
        phoneStrategy.sendNotification(title, message, employees);
    }
}

PhoneStrategy.java

public interface PhoneStrategy {

   public void sendNotification(String title, String message, List<String> listOfEmployeeIdGroupNamePhoneNumbers);
}

SendPhoneByPhoneNumbers.java

@Slf4j
public class SendPhoneByPhoneNumbers implements PhoneStrategy {

    RestTemplate restTemplate;
    String notificationServiceURL;
    BuildHttpRequest buildHttpRequest;

    public SendPhoneByPhoneNumbers(String notificationServiceURL) {
        this.notificationServiceURL = notificationServiceURL;
        this.restTemplate = new RestTemplate();
        this.buildHttpRequest = new BuildHttpRequest();
    }

    @Async
    public void sendNotification(String title, String message, List<String> phoneNumbers) {
        SmsMessage smsMessage= new SmsMessage(title, message, phoneNumbers, Collections.emptyList(), Collections.emptyList());

        try {
            HttpHeaders headers = new HttpHeaders();
            headers.set("idToken", buildHttpRequest.getNewToken());

            HttpEntity<SmsMessage> newRequest = new HttpEntity<>(smsMessage, headers);
            restTemplate.postForObject(notificationServiceURL + "/someUrl", newRequest, String.class);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
}

另外,如果你们对修改代码/结构以使其更好的方式有任何建议,请提出建议。

提前致谢。

【问题讨论】:

  • 不要像“PhoneServiceImpl notificationServiceImpl = new PhoneServiceImpl();”那样实例化spring管理的bean。而是注入它们。如果这些 bean 由 spring 管理,Spring 将能够注入属性。

标签: java spring spring-boot


【解决方案1】:
PhoneService phoneService = new PhoneService();

由于您使用的 PhoneService 不是 spring 容器的托管 bean,因此不会注入这些值。

代码改进和修复

String title="Title";
        String message="message";
        List<String> phoneNumbers = new ArrayList<>();
        phoneNumbers.add("333-222-1111");
        // PhoneService phoneService = new PhoneService();
        phoneService.sendNotificationByPhoneNumbers(title, message, phoneNumbers);

将此代码移至实现CommanLineRunnerApplicationRunner 的类并覆盖相应的run()。在这个类中,你可以 @Autowire PhoneService 而不是手动实例化它。另请注意,您必须使用 @Component 标记这个类

其他小的建议更改:

  1. 您可以将SendPhoneByPhoneNumbers 类设为单例。如果有多个实现,使用@Qualifier
  2. RestTemplateBuildHttpRequest 都可以使用@Bean 注解创建。
  3. 由于您使用的是lombok,所以也可以考虑使用@RequiredArgsConstructor

【讨论】:

  • 那你建议我如何使用/声明它?
  • 我使用了您的建议并添加了一个类 - codeshare.io/5008Ke 从 Demo.java 中删除了测试代码。在调试模式下运行 Demo.java,但得到了同样的错误。 “notificationServiceURL”仍然为空。
  • PhoneServiceImpl notificationServiceImpl = new PhoneServiceImpl(); - 必须注入而不是创建
  • 包含@Value 注解的类本身必须是一个Spring bean。在这种情况下,它将是PhoneServiceImpl
  • 由于我在任何类中都没有final字段,我还需要@RequiredArgsConstructor吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-01
  • 2017-07-09
  • 2019-05-19
  • 1970-01-01
相关资源
最近更新 更多