Mam klasę konfiguracyjną definiującą dwie fasole w zależności od wybranego profilu, z nadpisanymi metodami konfiguracji:
@Configuration
class MyConfig {
@Profile("profile")
@Bean
MyBean myBean(MyBeanProperties properties) {
return new MyBean(properties);
}
@Profile("!profile")
@Bean
MyBean myBean(MyBeanProperties properties, AdditionalProperties addProps) {
MyBean result = new MyBean(properties);
result.addAdditionalProperties(addProps);
return result;
}
}
I klasę, która automatycznie łączy MyBean
z nim
@Service
class MyService {
MyBean autowiredBean;
private MyService(MyBean bean) { this.autowiredBean = bean; }
}
Teraz, kiedy uruchamiam kontekst Spring, komunikat kończy się niepowodzeniem
Parametr 0 konstruktora w com.example.MyServce wymagał komponentu bean typu „com.example.MyBean”, którego nie można znaleźć.
Jak to możliwe? Jasno określam fasolkę wiosenną, więc powinna być obecna podczas tworzenia kontekstu.
3 odpowiedzi
Powodem tego jest fakt, że Spring uważa, że te komponenty bean mają tę samą nazwę ze względu na nazwę metody konfiguracji, więc nie tworzy ich instancji (chociaż w każdym aktywnym profilu należy utworzyć tylko jedną). To zadziała dobrze:
@Configuration
class MyConfig {
@Profile("profile")
@Bean
MyBean myBean(MyBeanProperties properties) {
return new MyBean(properties);
}
@Profile("!profile")
@Bean
// note different method name
MyBean otherBean(MyBeanProperties properties, AdditionalProperties addProps) {
MyBean result = new MyBean(properties);
result.addAdditionalProperties(addProps);
return result;
}
}
Nie znalazłem nigdzie wyjaśnienia tego zachowania, więc opublikowałem to pytanie, na które odpowiedziano samodzielnie.
W prawdziwym przypadku wydarzyło się to dla mnie, co za WebClient
, który został utworzony z rejestracją klienta w jednym profilu i bez jednego w drugim (ponieważ żaden nie był potrzebny do utworzenia filtra wymiany).
Dzieje się tak, gdy dwa ziarna są zdefiniowane z tą samą nazwą metody i jeden z nich ma zostać pominięty na podstawie jakiegoś warunku (w tym przypadku na podstawie profilu). W tym przypadku „myBean” jest definiowany dwukrotnie z różnymi profilami.
Sposób, w jaki klasa konfiguracyjna jest analizowana, polega na przejściu przez wszystkie metody beanMethods w tej klasie i dodaniu odpowiedniej definicji ziarna. Iteracja odbywa się w kolejności, w jakiej beanMethods są zdefiniowane w klasie konfiguracyjnej. Tu jest link do kodu.
W zależności od kolejności, w jakiej te komponenty bean są zdefiniowane w klasie konfiguracji, jeśli pierwszy zdefiniowany komponent bean ma zostać pominięty na podstawie adnotacji profilu, nazwa beanMethod zostanie dodana do listy beanMethod, które należy pominąć. Tu jest link do kodu.
Teraz, gdy napotka drugie ziarno o tej samej nazwie, widzi, że ta nazwa metody ziarnowej jest już obecna na liście metod „do pominięcia”, a zatem pomija ziarno, nawet jeśli nie ma nieodłącznego warunku (takiego jak profil) spowodowałoby to pominięcie. Tu jest link do kodu.
Zauważysz, że jeśli zmienisz kolejność ziaren i użyjesz tego samego profilu do uruchomienia, który wcześniej nie działał, fasola zostanie podniesiona.
Używanie unikalnych nazw beanMethod w klasie konfiguracji byłoby najlepszym sposobem na uniknięcie tego scenariusza.
Doszedłem do wniosku, dlaczego zmiana nazw metod pozwoliła na załadowanie kontekstu aplikacji:
Problem polega na tym, że pojemnik wiosenny wymaga, aby wszystkie ziarna miały unikalną nazwę, jak opisano tutaj https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#nazwa-fasoli
Każde ziarno ma jeden lub więcej identyfikatorów. Te identyfikatory muszą być unikalne w kontenerze, w którym znajduje się ziarno.
Kiedy nie używasz konfiguracji XML, myślę, że jedynym sposobem na posiadanie tej samej nazwy metody fasoli jest nadanie unikalnej nazwy fasolom w adnotacji @Bean(NAME)
, zobacz to, aby uzyskać szczegółowe informacje Spring-bean o tej samej nazwie metody, ale innym kwalifikatorze nie udało się załadować
Podobne pytania
Powiązane pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].
@Profile
zastosowany do Poziom kontrolera jako przykład