Spring boot @值注释字段返回@Service注释类的null方法
在Spring Boot 2.2.1.RELEASE的@Service注释类中使用@Value注释访问属性时,我遇到了一个奇怪的问题。该字段正在解析为null,我不确定如何调试它Spring boot @值注释字段返回@Service注释类的null方法,spring-boot,spring-annotations,Spring Boot,Spring Annotations,在Spring Boot 2.2.1.RELEASE的@Service注释类中使用@Value注释访问属性时,我遇到了一个奇怪的问题。该字段正在解析为null,我不确定如何调试它 @Service public class MyService { @Value("${my.username}") private String username; @Value("${my.password}") private String password; priva
@Service
public class MyService {
@Value("${my.username}")
private String username;
@Value("${my.password}")
private String password;
private RestTemplate restTemplate = getRestTemplate();
private RestTemplate getRestTemplate() {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
log.debug("Generating NTCredentials for RestTemplate using user: {} and password: {}", username, password);
credentialsProvider
.setCredentials(AuthScope.ANY,
new NTCredentials(username, password, null, "DOMAIN"));
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build();
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setHttpClient(client);
return new RestTemplate(clientHttpRequestFactory);
}
}
在这段代码中,getRestTemplate()方法中的用户名和密码总是为null。
我已确认属性存在于application.properties文件中
任何帮助都将不胜感激
编辑1:
@Slf4j
@Service
public class MyService {
@Value("${my.url}")
private String url;
private String username;
private String password;
private RestTemplate restTemplate = getRestTemplate();
public MyService(@Value("${my.username}") String username, @Value("${my.password}") String password) {
System.out.println(">> Inside Constructor");
this.username = username;
this.password = password;
}
public String updateDetails(String data) {
HttpEntity<String> entity = new HttpEntity<>(data);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
return response.getBody();
}
private RestTemplate getRestTemplate() {
System.out.println(">> Inside RestTemplate Method");
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
log.debug("Generating NTCredentials for RestTemplate using user: {} and password: {}", username, password);
credentialsProvider.setCredentials(AuthScope.ANY, new NTCredentials(username, password, null, "DOMAIN"));
HttpClient client = HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build();
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setHttpClient(client);
return new RestTemplate(clientHttpRequestFactory);
}
}
如您所见,getRestTemplate()是在调用构造函数之前被调用的。此外,在getRestTemplate()方法中,用户值和密码值都是null。但是,如果我在构造函数中初始化restTemplate,那么一切都可以正常工作
this.restTemplate = getRestTemplate();
我以为构造函数总是先被调用的。有人能解释一下吗?我认为这与访问restTemplate以实例化私有变量的方式有关。我是这样做的
@Autowire private RestTemplate restTemplate;
@Bean public RestTemplate restTemplate() {
...
}
通过这种方式,Spring可以控制何时实例化变量。我认为这与访问restTemplate以实例化私有变量的方式有关。我是这样做的
@Autowire private RestTemplate restTemplate;
@Bean public RestTemplate restTemplate() {
...
}
通过这种方式,Spring可以控制何时实例化变量。您正在调用
getRestTemplate()代码>同时声明类级别字段,这是在Spring框架对类进行膨胀之前,因此属性还不可用
尝试在类的构造函数中设置值。您可以通过将变量声明更改为:private restemplate restemplate代码>并添加此构造函数:
public MyService() {
this.restTemplate = getRestTemplate();
}
您正在调用getRestTemplate()代码>同时声明类级别字段,这是在Spring框架对类进行膨胀之前,因此属性还不可用
尝试在类的构造函数中设置值。您可以通过将变量声明更改为:private restemplate restemplate代码>并添加此构造函数:
public MyService() {
this.restTemplate = getRestTemplate();
}
使用构造函数注入
@Service
public class MyService {
private String username;
private String password;
@Autowired // optional if it is only single constructor
public MyService(@Value("${my.username}") String username, @Value("${my.password}") String password){
this.username=username;
this.password=password;
///its already here
}
通过这种方式,您可以保证在对象构造中必须提供和可用的值,因此稍后您将调用该类的任何方法
如果未提供值或SpEL无效,应用程序将无法启动。使用构造函数注入
@Service
public class MyService {
private String username;
private String password;
@Autowired // optional if it is only single constructor
public MyService(@Value("${my.username}") String username, @Value("${my.password}") String password){
this.username=username;
this.password=password;
///its already here
}
通过这种方式,您可以保证在对象构造中必须提供和可用的值,因此稍后您将调用该类的任何方法
如果未提供值或SpEL无效,应用程序将无法启动。完全膨胀MyService类以及任何其他bean,这都是错误的。我尝试了此操作,但用户名和密码字段仍然为空。@noobCoder属性是否成功拉入任何其他类?您是否验证了属性文件位于src/main/resources中?@NickJordan是的,其他类工作正常。事实上,在同一个类中,我有另一个方法,它使用@Value注释的方法,工作正常。@noobCoder好的,明白了,因此,如果在同一个类中有另一个使用@Value的方法,我将假设该方法不会作为类级变量实例化的一部分被调用,而是在类全部膨胀后在正常处理中被调用。问题是,当类膨胀时,这些属性的值在Spring的ApplicationContext中还不可用。你可以使用构造函数注入来回答这个问题,就像你在上面一个答案的评论中提到的那样,或者你可以…完全膨胀MyService类以及任何其他简单错误的bean,用户名和密码字段为空。@noobCoder属性是否成功拉入任何其他类?您是否验证了属性文件位于src/main/resources中?@NickJordan是的,其他类工作正常。事实上,在同一个类中,我有另一个方法,它使用@Value注释的方法,工作正常。@noobCoder好的,明白了,因此,如果在同一个类中有另一个使用@Value的方法,我将假设该方法不会作为类级变量实例化的一部分被调用,而是在类全部膨胀后在正常处理中被调用。问题是,当类膨胀时,这些属性的值在Spring的ApplicationContext中还不可用。你可以使用构造函数注入来回答这个问题,就像你在上述答案之一的评论中提到的那样,或者你可以…使用构造函数注入,你会没事的。使用构造函数注入,你会没事的。谢谢!我尝试按照您的建议使用构造函数注入,但问题仍然存在。然而,我能够通过结合您和@Nick Jordan的解决方案得到这些值。我使用了构造函数注入,然后从构造函数中调用getRestTemplate()方法。另外,在我上面发布的代码片段中,我添加了一个带有print语句的构造函数,并向getRestTemplate()方法添加了一个print语句。我看到getRestTemplate()方法在构造函数之前执行。我以为会先调用构造函数。你能帮我理解吗?我没有看到相关代码。是的,构造器的性质永远是第一位的。谢谢!我尝试按照您的建议使用构造函数注入,但问题仍然存在。然而,我能够通过结合您和@Nick Jordan的解决方案得到这些值。我使用了构造函数注入,然后从构造函数中调用getRestTemplate()方法。另外,在我上面发布的代码片段中,我添加了一个带有print语句的构造函数,并向getRestTemplate()方法添加了一个print语句。