#spring #spring-boot #spring-annotations
#spring #spring-boot #spring-аннотации
Вопрос:
Я совершенно уверен, что веду себя как идиот, но, хоть убей, я этого не вижу.
У меня есть большое приложение Spring Boot 2.1, которое широко использует внедрение свойств через аннотацию @Value. Это отлично работает, работает годами. Но есть один конкретный, совершенно новый объект, для которого я не могу установить значения. Они всегда равны нулю.
Я знаю, что проблема не в самих значениях, потому что некоторые из тех же значений просто отлично внедряются в другие объекты. Но я просто не вижу, что не так с ЭТИМ объектом, и был бы благодарен за ваши глаза.
Значения в этом объекте (который находится в том же каталоге и строится просто отлично) всегда равны null:
@Service
public class SSOUtil {
private String domain = "https://login.microsoftonline.com/";
private String tenantId = "[deleted guid]";
public static String localEnvironment = "local";
public static String devEnvironment = "dev";
public static String testEnvironment = "test";
public static String prodEnvironment = "prod";
@Value("${actions.PROD.touchnet_azure_ad_client_secret}")
private String clientSecretTouchnetProd;
@Value("${actions.TEST.touchnet_azure_ad_client_secret}")
private String clientSecretTouchnetTest;
@Value("${actions.DEV.touchnet_azure_ad_client_secret}")
private String clientSecretTouchnetDev;
@Value("${actions.touchnet_azure_ad_client_id_dev}")
private String clientIdDev;
@Value("${actions.touchnet_azure_ad_client_id_test}")
private String clientIdTest;
@Value("${actions.touchnet_azure_ad_client_id_prod}")
private String clientIdProd;
@Value("${touchnet.redirectURLDev}")
private String redirectURLDev;
@Value("${touchnet.redirectURLTest}")
private String redirectURLTest;
@Value("${touchnet.redirectURLProd}")
private String redirectURLProd;
private String clientId;
private String clientSecret;
private String redirectURI;
public SSOUtil() {
this.redirectURI = redirectURLTest;
this.clientSecret = clientSecretTouchnetTest;
}
public String getADLoginURL() {
String returnURL = "";
System.out.println(clientIdTest); // always prints null
}
}
Однако значения в этом объекте работают просто отлично, и обратите внимание, что одно из них является тем же @Value, что и в другом классе:
@Service
public class LibraryHelpServiceBean implements LibraryHelpService {
private CourseServiceBean courseServiceBean;
private final RestTemplate restTemplate;
@Value("${actions.libraryhelp_lti_api_key}")
private String apikey;
@Value("${actions.touchnet_azure_ad_client_id_test}")
String clientIdTest;
public LibraryHelpServiceBean(CourseServiceBean courseServiceBean, RestTemplateBuilder restTemplateBuilder) {
this.courseServiceBean = courseServiceBean;
this.restTemplate = restTemplateBuilder.build();
}
public void doesValueWork() {
this.apikey = this.apikey;
System.out.println(this.clientIdTest); // always prints correct value, a guid
}
}
Оба объекта инициализируются аналогичным образом: прямо или косвенно через аннотацию @Autowired в других объектах, которые я использую (и которые отлично работают и отлично работали целую вечность). Вот создание SSOUtil (мой проблемный класс):
@RestController
@RequestMapping(value = "/web")
public class SSOLandingController {
@Autowired
private SSOUtil ssoUtil;
[rest of class omitted]
}
И вот создание LibraryHelpServiceBean, который работает нормально и все @Values заполняются правильно:
@Service
public class LibraryHelpStreamServiceBean implements LibraryHelpStreamService {
private LibraryHelpServiceBean libraryHelpServiceBean;
public LibraryHelpStreamServiceBean(LibraryHelpServiceBean libraryHelpServiceBean){
this.libraryHelpServiceBean = libraryHelpServiceBean;
}
}
Я уже пробовал изменить аннотацию класса для SSOUtil с @Service на @Component (и @Configuration, просто так).
Что может быть причиной того, что @Values в SSOUtil возвращает значение null, даже если некоторые из тех же @Values отлично заполняются в других классах?
Я убежден, что мне не хватает чего-то очевидного. Я надеюсь, что это что-то маленькое, например, опечатка. Я нервничаю, что это что-то большое, как будто я совершенно неправильно понял, как работает Spring IOC в течение последних нескольких лет.
Спасибо за вашу помощь.
Комментарии:
1. Привет и добро пожаловать! В каком пакете («каталоге») находится
SSOUtil
? .. он подбирается с помощью сканирования компонентов / автоматической настройки ?? 😉2. Можете ли вы поделиться своей структурой проекта? Кроме того, попробуйте переместить все свои свойства в один класс @Component с помощью getter и setters, а затем вводить класс всякий раз, когда вы хотите использовать свойства.
3. Большое вам спасибо за любезный прием! Оба находятся в одном пакете, package edu.mycompanyname.its.actions.service . Библиотечная помощь;
4. И, Дэни, я думаю, что это отличный обходной путь, спасибо. Вероятно, я сделаю именно это, если не смогу разобраться в этом к полудню или около того в пятницу. Структура проекта довольно обширная — я унаследовал ее много лет назад, и у меня никогда не было проблем с ее расширением, поэтому я не могу легко поделиться здесь (и в любом случае это было бы не очень понятно). Но я думаю, что важным фактом является то, что и LibraryHelpServiceBean, и SSOUtil находятся в одном пакете, и у LibraryHelpServiceBean нет проблем с проверкой компонента.
Ответ №1:
Я проверил ваш случай на своем компьютере, но я не могу воспроизвести вашу проблему. Когда происходят подобные вещи, попробуйте что-то очень простое, например
package no.mycompany.springbootapp;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class SSOUtil2 {
@Value("${actions.touchnet_azure_ad_client_id_test}")
private String clientIdTest;
}
Вставьте этот компонент в свой контроллер, установите точку останова внутри вашего метода контроллера и проверьте введенный экземпляр.
По моему опыту, некоторые необъяснимые случаи, в которых я участвовал здесь, на SO, были решены путем очистки сборки или удаления папки .m2.