Aufspüren Ursache für Spring „nicht für Auto-Proxying“
Frage
Wenn Sie um mit Spring Auto-Proxy Sachen beginnen verwirren, Sie oft in dieses Verhalten führen, wie dokumentiert:
Klassen, die die Umsetzung BeanPostProcessor Schnittstelle sind Besonderes, und so behandelt sie anders durch den Behälter. Alle BeanPostProcessors und ihre direkt referenzierten Bohnen werden instanziiert beim Start, als Teil des Sonder Anlaufphase des Application, dann alle, BeanPostProcessors werden registriert in einer sortierten Art und Weise - und auf alle weiteren Bohnen. da AOP Auto-Proxying wird als umgesetzt BeanPostProcessor selbst, nein BeanPostProcessors oder direkt referenzierten Bohnen sind für Auto-Proxying (und wird somit nicht haben Aspekte 'gewebt' in sie.
Für eine solche Bohne, sollten Sie eine sehen info Protokollmeldung: „Bean‚foo‘ist nicht Anspruch auf die von allen verarbeitet zu werden BeanPostProcessors (zum Beispiel: nicht fähigen Auto-Proxying)“.
Mit anderen Worten, wenn ich meine eigene BeanPostProcessor schreiben, und diese Klasse verweist direkt andere Bohnen im Zusammenhang, dann die referenzierten Bohnen nicht für Auto-Proxying berechtigt sein, und eine Nachricht in diesem Sinne Urteil angemeldet ist.
Mein Problem ist, dass das Aufspüren von wo der direkten Bezug wird sehr schwierig sein kann, da die „direkte Referenz“ kann in der Tat eine Kette von transitiven Abhängigkeiten, die in der Hälfte der Bohnen in dem Anwendungskontext Aufnahme endet. Alle Frühling gibt Sie, dass einzelne Info-Nachricht ist, und es ist nicht wirklich viel helfen, über Ihnen zu sagen, wenn eine Bohne hat in diesem Netz von Bezügen gefangen.
Die BeanPostProcessor Ich entwickle hat direkte Verweise auf andere Bohnen, aber es ist eine sehr begrenzte Anzahl von Referenzen. Trotzdem, so ziemlich jede Bohne in meinem Kontext wird dann davon, dass Auto-proxied ausgeschlossen wird, nach den Log-Meldungen, aber ich kann nicht sehen, wo diese Abhängigkeit geschieht.
Hat jemand einen besseren Weg der Verfolgung dieses gefunden down?
Lösung 2
Nur einige Schließung auf diese Frage zu bringen, wurde der Zusammenbruch des nicht initialisierten Objektgraphen durch die BeanPostProcessor
verursacht @Autowired
mit seinen Abhängigkeiten zu bekommen, und der autowire Mechanismus verursachte effektiv jede andere Bohne Definition initialisiert werden, bevor mein BeanPostProcessor
eine Chance ein Mitspracherecht in der Sache zu haben. Die Lösung wird nicht autowiring für Ihre BPPs zu verwenden.
Andere Tipps
Folgen Sie dieses Rezept:
- Öffnen
BeanPostProcessorChecker
in Ihrem IDE (es ist eine innere Klasse vonAbstractApplicationContext
) - einen Haltepunkt auf
if (logger.isInfoEnabled()) {
im VerfahrenpostProcessAfterInitialization
Set - Führen Sie den Code
-
Wenn Sie den Haltepunkt erreicht, sucht Anrufe in Ihrem Stack-Trace
getBean(String,Class<T>)
.Einer dieser Anrufe werden versuchen, eine
BeanPostProcessor
zu erstellen. Das Bohne sollte die Ursache sein.
Hintergrund
Stellen Sie sich diese Situation:
public class FooPP implements BeanPostProcessor {
@Autowire
private Config config;
}
Wenn der Frühling config
zu erstellen hat (da es eine Abhängigkeit von FooPP
ist), hat es ein Problem: Der Vertrag besagt, dass alle BeanPostProcessor
auf jede Bohne angewandt werden müssen, die erstellt wird. Aber wenn der Frühling config
braucht, gibt es mindestens eine PP (nämlich FooPP
), die für den Dienst nicht bereit ist!
Dies wird noch schlimmer, wenn Sie eine @Configuration
Klasse verwenden diese Bean zu definieren:
@Configuration
public class BadSpringConfig {
@Lazy @Bean public Config config() { return new Config(); }
@Lazy @Bean public FooPP fooPP() { return new FooPP(); }
}
Jede Konfigurationsklasse ist eine Bohne. Das bedeutet eine BeanFactory von BadSpringConfig
zu bauen, braucht Frühling den Postprozessor fooPP
anzuwenden, sondern um das zu tun, muss er zunächst die BeanFactory ...
In diesem Beispiel ist es möglich, eine der zyklischen Abhängigkeiten zu brechen. Sie können FooPP
implementieren BeanFactoryAware
machen zu bekommen Frühling die BeanFactory
in den Postprozessor injizieren. Auf diese Weise, die Sie nicht autowiring benötigen.
Später im Code können Sie träge für die Bean fragen:
private LazyInit<Config> helper = new LazyInit<Config>() {
@Override
protected InjectionHelper computeValue() {
return beanFactory.getBean( Config.class );
}
};
@Override
public Object postProcessBeforeInitialization( Object bean, String beanName ) throws BeansException {
String value = helper.get().getConfig(...);
}
Um den Kreislauf zwischen der BeanFactory brechen und dem Postprozessor, müssen Sie den Postprozessor in einer XML-Konfigurationsdatei konfigurieren. Frühling kann man erkennen, lesen und baut alle Strukturen ohne verwirrt zu werden.
Nicht sicher, ob es eine Hilfe ist, aber die Eclipse- Frühling IDE 's Graph Ansicht sieht aus wie es bean Referenzen in Aussortieren hilfreich sein könnte ..