Spring ApplicationContext: Fortschritt der Instanziierung von Beans?

Hallo ihr beiden,

ich möchte die fachliche Diskussion nicht unterbrechen, aber beim weiteren Durchlesen von Spring-Dokus (ich bin ja immernoch in der Lernphase) habe ich etwas über das Lazy-Loading gelesen.

Wie wäre es denn, wenn man standard Lazy-Loading für das <beans /> Element aktiviert (default-lazy-init="true"), sodass erstmal keine Beans instanziiert werden, wenn der Context erzeugt wird.

Dann holt man sich im Code über den ApplicationContext alle Bean Definitionen (getBeanDefinitionNames()) und lädt diese "manuell". Da man über "getBeanDefinitionCount()" ebenfalls die Anzahl kennt, hat man so also einen ungefähren Fortschritt.

Ist das eine eher "blöde" Lösung, oder darf ich mir ganz kurz auf die Schulter klopfen? :)
 
Nunja, das bewirkt eigentlich nur, dass die Beans erst nach und nach instantiiert werden. Ansonsten macht der BeanFactoryPostProcessor ja genau das. Er wird ausgeführt, nachdem die BeanFactory BeanDefinitionen gebildet hat.

Mit dem LazyLoading gibst du halt das Feature aus der Hand, dass implizit ein Check der Anwendungskonfiguration gemacht wird. Mit LazyLoading fliegt halt unter Umständen erst recht spät eine Exception, dass irgendeine Bean nicht gefunden werden kann.

Gruß
Ollie
 
Ja gut, das verstehe ich, reicht in meinem Fall aber aus. Es geht mir momentan nur darum, dem Benutzer (ich schreibe an einer Desktop Anwendung) eine visuelle Rückmeldung über den Ladevorgang zu geben. Da einige Beans eine Initialisierungszeit von 2 bis 3 Sekunden haben, macht mein Vorgehen für mich jedenfalls gerade Sinn.

Ob die Konfiguration richtig ist, sehe ich dann ja schon sehr früh in der Initialisierungsphase des Programmes.

Eine Sache, die ich mich in diesem Zusammenhang jedoch frage ist Folgendes:

beanA, beanB und beanC werden in beanD injiziert. Nehmen wir weiter an, dass beanD vor A, B und C instanziiert wird, da ich es vorher mit context.getBean(..) hole. Instanziiert dann Spring automatisch auch A, B und C um es D zu injizieren?
 
Ich hätte da nochwas im Angebot. Wenn ich meinen Context so lade:

Code:
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);  
xmlReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
xmlReader.loadBeanDefinitions(is); // InputSource auf XML Daten
ctx.refresh();

dann könnte ich einen ReaderEventListener an den Reader hängen, der mir dann bescheid gibt, wenn Beans instanziiert wurden.

Ich finde das Thema mittlerweile sehr spanned, es gibt da ja anscheinend viele Möglichkeiten....
 
Ob die Konfiguration richtig ist, sehe ich dann ja schon sehr früh in der Initialisierungsphase des Programmes.

Nunja, viele kritische Punkte bleiben so lang unentdeckt bis die Bean wirklich instantiiert wird. Ob sie einen AOP Proxywrapper bekommt, ob die Typen stimmern usw.

beanA, beanB und beanC werden in beanD injiziert. Nehmen wir weiter an, dass beanD vor A, B und C instanziiert wird, da ich es vorher mit context.getBean(..) hole. Instanziiert dann Spring automatisch auch A, B und C um es D zu injizieren?

Richtig, anders ginge es ja nicht ;). D.h. bei den meisten Anwendungen ist es kaum so, dass viele Beans lazy instantiiert werden können.

Das mit dem BeanDefinitionReader klingt auf jeden Fall nach dem Weg, der sinnvoll ist.

Gruß
Ollie
 
Hallo Oliver,

Nunja, viele kritische Punkte bleiben so lang unentdeckt bis die Bean wirklich instantiiert wird. Ob sie einen AOP Proxywrapper bekommt, ob die Typen stimmern usw.

Nunja, mein Vorhaben ist ja:

1. Context erstellen
2. In einer Schleife alle Beans manuell laden

Also werden ja alle kritischen Punkte "quasi sofort" entdeckt. Allerdings macht mir die Sache mit dem, ich nenne es mal kaskadierenden Instanziieren, natürlich einen Strich durch die Rechnung.

Das mit dem BeanDefinitionReader klingt auf jeden Fall nach dem Weg, der sinnvoll ist.

So habe ich es nun auch umgesetzt, und es funktioniert wunderbar :)
 
Kleines Update: die Idee, einen ReaderEventListener zu benutzen, hat sich erledigt. Der benachrichtigt einen nur, wenn eine Bean Definition gelesen wurde, nicht instanziiert.
 
Ehrlich gesagt, ich dachte es würde so funktionieren :) Nunja, momentan mache ich es doch wieder auf die Art meiner ersten Idee, da sich Toms Vorschlag momentan nicht so gut in meine Applikation integriert. Letztendlich ist es auch ok so, denn es werden bei mir viele Beans instanziiert, die keine großen Abhängigkeiten haben. Der Fortschritt ist in meinem speziellen Fall also doch schon repräsentativ.
 
Hallo,

genaue Informationen über den Anwendungsstart wirst du über den Spring Context nicht bekommen, denn dort sind nicht nur Singleton Beans (die womöglich lazy, also erst viel später erzeugt werden) sondern auch Prototype Beans definiert.
Aus diesen Prototype Definitionen können (mehr oder weniger parameterisierbar) beliebig viele Instanzen erzeugt werden.

Die von mir vorgeschlagene Variante wäre nur dann (halbwegs) genau wenn nur Singleton Beans definiert wären die beim Starten sofort initialisiert werden würden.

Alles andere ist ein nur PI * Daumen....

Aber wie so oft kann man den Benutzern mit ein wenig Geschick Start-Fortschritt vorgaukeln. Dabei setzt man einfach an bestimmten Punkten im Start-Prozess "Marken" zu welchen Anteilen der Startprozess fortgeschritten ist. Damit es nun keine Sprünge zwischen zwei Marken gibt, nähert man von der unteren Marke die obere Marke logarithmisch an.
Wenn man das richtig austariert, sieht der Benutzer einen smoothen Fortschrittsbalken
und hoffentlich bald die Anwendung. Dabei wird die Progressbar über einen seperaten Thread animiert.

Gruß Tom
 
Zurück