Pewnie tworząc beany nie raz trafiłeś na sytuację, w której rozpatrywana klasa implementuje więcej niż jeden interfejs. Okazuje się, że najlepszą metodą rejestrowania takiego beana jest rejestrowanie go jako typu najbardziej specyficznego (sekcja TIP).

1
2
public class ExampleClass implements A, B {
}
1
2
3
4
5
public class FirstClass {

	private final A a;

}
1
2
3
4
5
public class SecondClass {

	private final B b;

}

Załóżmy, że mamy sytuację jak powyżej. W przykładzie istnieją dwa kontrakty w postaci interfejsów A i B. Klasa FirstClass zależy od kontraktu A, natomiast SecondClass od B. Zwieńczeniem tych dwóch kontraktów jest klasa ExampleClass. Po tym przedstawieniu pora wziąć się na zarejestrowanie instancji tych klas jako beany.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration(proxyBeanMethods = false)
public class SpecificTypeConfiguration {

	@Bean
	public FirstClass firstClass(A a) {
		return new FirstClass(a);
	}

	@Bean
	public SecondClass secondClass(B b) {
		return new SecondClass(b);
	}

	@Bean
	public ExampleClass exampleClass() {
		return new ExampleClass();
	}

}

Przy tej okazji odsyłam do wpisu na temat @Configuration, gdzie wyjaśnione zostało działanie proxyBeanMethods = false. Dobra, z powyższej konfiguracji najistotniejsza jest rejestracja beana exampleClass. W myśl wskazówki z dokumentacji Springa zapisałem najbardziej specyficzny typ, czyli nie A ani B tylko ExampleClass. Próba uruchomienia aplikacji powinna zakończyć się sukcesem. I tak też jest! Natomiast co by się stało w przypadku, gdyby ten typ był tylko jednym z interfejsów?

1
2
3
4
5
6
7
8
9
@Bean
public A exampleClass() {
    return new ExampleClass();
}

@Bean
public SecondClass secondClass(B b) {
	return new SecondClass(b);
}

O dziwo aplikacja wstaje! Zależność dla SecondClass w postaci B została spełniona pomimo ostrzeżenia IntelliJ jakie można zauważyć przed uruchomieniem serwisu:

Could not autowire. No beans of ‘B’ type found.

Wychodzi na to, że Spring potrafi sobie poradzić z takim “problemem” (przykład był uruchamiany na wersji 3.3.2 Spring Boot - być może wcześniejsze wersje Springa nie posiadały takiego mechniazmu). Jednak zachęcam do stosowania się do wskazówki znajdującej się w dokumentacji. To podejście wydaje się logiczniejsze, a przy okazji IDE nie będzie nas wprowadzało w błąd o nieistniejącej zależności.