Wie Autowire eine Feder-annotierten service-Klasse in @Configuration-Klasse?
Ich versuche zu injizieren einer service-annotierten Klasse in eine configuration-Klasse, die in einer Spring-Boot-Anwendung, aber es wird nicht injiziert (auf null gesetzt), was ich davon ausgehen ist, aufgrund der Feder lifeycle.
Auch, dieser Dienst hat einen überladenen Konstruktor, der verwendet Konstruktor-Injektion, und ich denke, das ist auch ein problem, wie autowiring wirkt auf einen default-Konstruktor. Allerdings muss der Dienst werden Frühjahr-konfiguriert, so dass ich nicht denke, man kann eine neue Instanz erstellen, in einer Bean annotierten Methode.
Wie kann man dieses Problem lösen?
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private SessionService sessionService;
@Bean
public SessionService sessionService() {
return sessionService;
}
}
public interface SessionService extends BaseCacheService<Session> {
void extendExpiration(String key);
String getSessionId(String key);
}
@Service
public class SessionServiceImpl implements SessionService {
private Environment environment;
private UserService userService;
@Autowired
public SessionServiceImpl(Environment environment, UserService userService) {
this.environment = environment;
this.userService = userService;
}
}
Wenn ich ausschließen @Bean-Methode, dann bekomme ich einen Kompilierungsfehler:
- Warum haben Sie eine
@Bean
Methode für Sie, wenn Sie mit@Service
? - Entfernen Sie die
@Bean
Methode. Die@Service
ist im Grunde eine@Component
welche bekommt, entdeckt mit Kommentar-scanning. Vorausgesetzt, Sie haben das setup. Kurz gesagt, Sie brauchen nicht die@Bean
Methode überhaupt. Ihre Annahme ist falsch, auto-Bordnetz hängt nicht von default-Konstruktoren. - Können Sie zeigen Sie Ihre SessionService-Schnittstelle? Denn Sie wollen autowire, Schnittstelle, vielleicht gibt es etwas falsch?
- Warum brauchen Sie SessionService Schnittstelle in SecurityConfiguration? Ich verstehe nicht wirklich der Fall für, die. Ich habe versucht, verschiedene Implementierung von autowire eine Schnittstelle-und alles wo ok.
- Es ist erforderlich, durch meine http-filter, der ist initialisiert. Die
@Configuration
annotation zu sein scheint die dieses Problem verursachen - Erstellt habe ich ein Beispiel-Projekt, und ich bin in der Lage, autowire die Schnittstelle. Ich habe Ihre ersten Ansatz mit
@Bean
annotation. Alles andere sollte den Fehler erzeugt
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihre Fehler ist die folgende (Sie sind Rückgabe eines null-Wert):
Lösung
Seit Ihr
SessionServiceImpl
versehen mit@Service
, können Sie einfach entfernen Sie die@Bean
Methode und lassen Sie das Frühjahr erstellen. Frühling ist es bereits verfügbar für Sie.Oder, Wenn Ihr
SessionServiceImpl
war nicht annotiert mit@Service
, müssen Sie die folgenden :Wenn das nicht funktioniert, könnte es einfach sein, dass Ihr
SessionServiceImpl
ist, die in einem Paket nicht gescannt wird, wird durch die Feder (vorgeschlagen von @Miloš Milivojević)Können Sie
@ComponentScan
zu Ihrer Konfiguration Klasse@ComponentScan
annotation sortiert Sie es aus! Würde wirklich gedacht habe, dass die Komponente Scannen wäre schon gewesen von der Haupt-Spring-Boot-Anwendung Klasse durch die Zeit, die diese Konfiguration der Klasse initialisiert wird. Es stellt sich heraus, dass meine IDE war Herumspielen, wie ich die entfernt@Bean
Methode und begann dann, die app, und dann ist die Kompilierung Fehler verschwunden. Ich konnte das nicht irgendwie erstellen Sie eine Instanz der SessionService in einem@Bean
Methode, denn es muss gespritzt werden, da es parametrisierten Konstruktor erfordert WLAN-Komponenten.Weiter geht ' s mit @Alex die Antwort, wenn Sie kommentieren eine Methode, die mit @Bean, es sagt Spring, die diese Methode produziert, der Typ. Also, Sie im wesentlichen gesagt Frühling geben Sie die null-Referenz, die Sie bereits für alle Bohnen der Art SessionService.
Wenn Sie Annotation-basierten-Kontext der Konfiguration können Sie
Autowire
alle@Component
Bean (nicht nur@Service
), die konstruiert werden können, die ohne runtime-Parameter (z.B. ein default-Konstruktor oder ein Autowired-Konstruktor). Wenn Sie müssen etwas tun, um erstellen die Bohne (z.B. Laufzeit-Konfiguration erforderlich), müssten Sie entweder erstellen Sie eine Methode als @Alex vorgeschlagen, oder Sie können getBean und übergeben Sie den Typ und Konstruktor-Argumente. Die erstere ist in der Regel bevorzugt.@Order
Anmerkung ist zu machen, es zu versuchen, diese zu erstellen-Konfiguration-Klasse vor allem anderen. Ich glaube nicht, sollten Sie haben, um@ComponentScan
auf IhreConfiguration
Klasse (wie Sie erwähnen anderswo, ist bereits in derSpringBootApplication
). Ich kannAutowire
alle Arten vonComponent
s in meinemConfiguration
Klassen.@Bean
Methode definiert ist, aber die Anwendung funktioniert Prima. Sie können entweder deaktivieren, dass die Prüfung oder Beurteilung@SuppressWarnings("SpringJavaAutowiringInspection")
zu denAutowired
Felder.Ich Stand vor ähnlichen Problem beim schreiben eines integration test-Klasse für eine spring-boot-Anwendung. Klasse RestTemplate und CounterService von Metriken API sind autowired in meinem service-Klasse. Ich könnte @ContextConfiguration(Classes={RestTemplate.class}) für die Injektion RestTemplate auf meinen Dienst, aber das hinzufügen CounterService.class oben annotation nicht helfen, vielleicht weil CounterService ist eine Schnittstelle, die nicht einer konkreten Klasse, Daher war ich immer "No bean vom Typ CounterService gefunden" - Problem.
Dank Antwort von Milos, habe ich @EnableAutoConfiguration zu meiner integration test-Klasse, Problem wurde gelöst!
Wenn Alex ' Antwort nicht arbeiten (entfernen der @Bean-Methode), sind Sie wahrscheinlich nicht mit @EnableAutoConfiguration oder Ihre Anwendung ist nicht in der Wurzel-Hierarchie-Paket, so dass Sie nicht Scannen die gesamte Klassenpfad. Versuchen Sie
@ComponentScan("service.class.package")
zu Ihrer Konfiguration (zusätzlich zu dem entfernen der sessionService-Methode) und sehen, ob es hilft.@SpringBootApplication
Anmerkung in der main-Klasse befindet sich in dem root-Paket beinhaltet bereits, dass. So würde das Scannen für alle Komponenten.