1. Vorwort
Wir wissen, dass der Frühling faul laden kann, das heißt, die Bohne zu instanziieren, wenn sie tatsächlich verwendet wird. Dies ist natürlich nicht der Fall. Das Konfigurieren der Laken-Init-Eigenschaft einer Bohne kann beispielsweise die Ladezeit der Feder steuern. Jetzt sind die Leistung, der Speicher usw. der Maschine relativ hoch und verwenden im Grunde keine faulen Laden. Die Bohne ist zu Beginn des Behälters geladen und die Startzeit ist etwas länger. Auf diese Weise kann die Bohne, wenn die Bohne tatsächlich für die geschäftliche Verwendung erhalten wird, eine Menge Belastung reduziert werden. Dies wird später analysiert. Wenn wir Bohnen verwenden, besteht die direkteste Möglichkeit, sie von Spacktroy zu holen, was die Quelle für die Belastung von Bohneninstanzen ist.
Vor kurzem habe ich bei der Arbeit an Projekten auf ein seltsames Problem gestoßen, dh die Genauigkeit der Bean -Abhängigkeitsinjektion hängt mit der Reihenfolge der Bean -Direktinjektion zusammen, aber unter normalen Umständen hat es nichts mit der Reihenfolge zu tun. Wenn Sie es eilig haben, lassen Sie mich Ihnen nacheinander sagen.
2. Gewöhnliche Bean cyclische Abhängigkeit nicht mit der Injektionsordnung in Bezug auf die Injektionsordnung
2.1 Beispiele und Prinzipien für kreisförmige Abhängigkeiten
öffentliche Klasse Beana {private beanb beanb; public beanb getBeanb () {return beanb;} public void setbeanb (Beanb Beanb) {this.beanb = beanb;}}} öffentliche Klasse Beanb {private Beana Beana; public beana getbeana () {return beana;} public void setbeana (Beana Beana) {this.beana = beana;}}}<bean id = "beana"> <Eigenschaft name = "beanb"> <ref bean = "beanb"/> </property> </bean>
<bean id = "beanb"> <Eigenschaft name = "beana"> <ref bean = "beana"/> </property> </bean>
Die oben genannte zirkuläre Abhängigkeitsinjektion funktioniert normalerweise, da die Frühling frühbezählte Funktion bietet. Zunächst gibt es im Frühjahr eine gleichzeitige Karte mit dem Namen SingletonObjects, um alle instanziierten und initialisierten Bohnen zu speichern, während SingletonFactores verwendet werden, um Bohneninformationen (Beanname und eine Callback -Fabrik) zu speichern, die gelöst werden muss. Bei der Instanziierung von Beana getBean(“beanA”); Sehen Sie zunächst an, ob es Beana in SingletonObjects gibt, es wird zurückkehren:
(1)
Object SharedInstance = Getsingleton (Beanname); // Getsingleton (Beanname, true); if (SharedInstance! '" + BeAnName +"', der noch nicht vollständig initialisiert ist - eine Folge einer kreisförmigen Referenz "); } else {logger.debug ("zurückgegebene Instanz von Singleton Bean '" + BeAnName + "'"); }} // Wenn es sich um eine normale Bean handelt, gibt es SharedInstance. Protected Object Getsingleton (String beanname, boolean erlaubtearterferenz) {Object SingletonObject = this.singletonObjects.get (Beanname); if (SingletonObject == null) {synchronized (this.singletonObjects) {SingletonObject = this.ErlysingletonObjects.get (BeAnName); if (SingletonObject == null && duldearLeferference) {ObjectFactory SingletonFactory = (ObjectFactory) this.singletonFactory.get (BeAnName); if (SingletonFactory! = null) {SingletonObject = SingletonFactory.getObject (); this. this.singletonfactory.remove (Beanname); }}} return (SingletonObject! = null_object? SingletonObject: null);} Zu Beginn gibt es definitiv keine Beana. Wenn es also zulässt, dass allowCircularReferences=true festgelegt ist (Standard ist wahr) und die aktuelle Bean einzeln und die Bean erstellt wird, geben Sie vor dem Initialisieren des Attributs die Bohneninformationen in die SingletonFactores-Einstellkarte:
(2)
boolean eargingletOnexposure = (mbd.issingleton () && this.allowcircularReferences && issingletoncurentincreation (Beanname));
if (frühsingletOnexposure) {if (logger.isdebugenabled ()) {logger.debug ("Sesselndes Caching Bean '" + BeAnName + "', um potenzielle zirkuläre Referenzen aufzulösen. GetearlyBeanReference (Beanname, MBD, Bean); Protected Void addSingletonFactory (String Beanname, ObjectFactory SingletonFactory) {assert.notnull (SingletonFactory, "Singleton Factory dage this.singletonFactory.put (Beanname, SingletonFactory); this. this.registeredsingletons.add (Beanname); }}} Injizieren Sie dann die BeanB in das Instanzattribut. Bei der Injektion des Attributs, getBean(“beanB”) und feststellen, dass Beanb nicht in SingletonObjects ist, wird es Beanb instanziiert, dann SingletonFactores einfügt, dann die Beana injiziert und dann getBean(“beanA”); Zu diesem Zeitpunkt wird Getsingleton die sofortige Beana zurückgeben. Nach der Initialisierung der BeanB fügen Sie Beanb zu SingletonObjects hinzu und kehren Sie dann zurück. Dann wird Beana initialisiert, Beana zu SingletonObjects und dann zurückkehren und dann zurückkehren
2.2 Schalter, die Schleifenabhängigkeiten ermöglichen
public class testcircle2 {private endgültige statische classPathxMlApplicationContext moduleContext; moduleContext.setallowcircularReferences (false); test = (test) moduleContext.getbean ("test");} public static void main (String [] args) {System.out.println (test.name);}}Es gibt eine Eigenschaft zulässigen CircularReferences in der ClassPathXMLApplicationContext -Klasse, um zu steuern, ob kreisförmige Abhängigkeiten standardmäßig wahr sein dürfen. Nachdem es auf False gesetzt ist, wird festgestellt, dass kreisförmige Abhängigkeiten immer noch normal laufen können. Schauen Sie sich den Quellcode an:
public classPathXmlApplicationContext (String [] configLocations) löst beansexception {this (configLocations, true, null);} aus public classPathXmlApplicationContext (String [] configLocations, boolean aktualisiert, applicationContext übergeordnet) löst beansexception {super (übergeordnet); setConFiglocations (configLocations); if (reprosh) {reprosh ();}} aus public classPathXmlApplicationContext (String [] configLocations, boolean aktualisiert, applicationContext übergeordnet) löst beansexception {super (übergeordnet); setConFiglocations (configLocations); if (reprosh) {reprosh ();}} aus Wisse, dass der Container aktualisiert wird, wenn der ClassPathXMLApplicationContext standardmäßig konstruiert wird.
Die Aktualisierungsmethode ruft RefreshBeanFactory auf:
geschützte endgültige void refreshbeanFactory () löst Beansexception {if (hasBeanFactory ()) {destroyBeans (); CloseBeAnfactory ();} try {// Bean Factory DefaultListableBeanFactory beanfactory = CreateBeanFactory (); // Bean Factory Properties CustomizeBeAnfactory (Beanfactory) anpassen; LoadbeanDeFinitions (Beanfactory); synchronisiert (this.beanFactoryMonitor) {this.beanfactory = beanfactory; }} catch (ioException ex) {Wurf New ApplicationContexception ("E/O -Fehler Parsen XML -Dokument für Anwendungskontext [" + getDisplayName () + "]", Ex);}} Protected Void CustomizeBeArfactory (DefaultListableBeanFactory Beanfactory) {if (this.allowbeandeFinitionOversionRiding! beanfactory.setallowcircularReferences (this.allowcircularReferences.booleanValue ());}} Sie werden hier wissen, dass der CustomizeBeAnfactory des von der Frühlings hinterlassenen CustomizeBeAnfactory der CustomizeBeAnfactory ausgeführt wurde, bevor wir moduleContext.setAllowCircularReferences(false) aufrufen. Der letzte Grund ist, dass die Bean -Fabrik vor dem Aufrufen der Einstellungen aktualisiert hat, sodass der Testcode in Folgendes geändert wird:
public class testcircle {private endgültige statische classPathxmlapplicationContext moduleContext; moduleContext.setallowcircularReferences (false); // den Container moduleContext.refresh () aktualisieren; test = (test) moduleContext.getbean ("test");} public static void main (String [] args) {System.out.println (test.name);}}Jetzt wird der Test eine Ausnahme machen:
Verursacht durch: org.springframework.bean.factory.beancreationException: Fehler erstellen Bean mit Namen 'Beana' in der Klassenpfadressource [bean-circile.xml]: Verweis nicht auf Bean 'Beanb' auflösen, während die Bean-Eigenschaft 'Beanb' festgelegt wird. Eine verschachtelte Ausnahme ist org.springframework.bean.factory.beancreationException: Fehler erstellen Bean mit Namen 'Beanb' in der Klassenpfadressource [bean-circile.xml]: Verweis nicht auf Bean 'Beana', während Bean-Eigenschaft 'Beana' festgelegt wird. Verschachtelte Ausnahme ist org.springframework.bean.factory.beancurentincreationException: Fehler erstellen Bean mit Name 'Beana': Angeforderte Bean ist derzeit in der Erstellung: Gibt es eine unlösbare Zirkularreferenz?
3. Fabrikbohnen und gewöhnliche Bohnen zyklische Abhängigkeiten - im Zusammenhang mit der Injektionsordnung
3.1 Testcode
Fabrikbohne
öffentliche Klasse MyFactoryBean implementiert FactoryBean, Initialisierungsbean {private String -Name; privater Test; public String getName () {return name;} public void setName (String name) {this.name = name;} public abhängigbean getDepentBean () {return abendendBean; abhängigBean;} private abhängige Abhängigkeit abhängigbean; public Object getObject () löst Ausnahme aus {return test;} öffentliche Klasse getObjecttype () {// Todo automatisch generierter Methode Stub return.class; System.out.println ("Name:" + this.name); Test = neuer Test (); test.name = abhängigbean.dosomething () + this.name;}} Schreiben Sie einfach eine öffentliche Variable
public class test {public string name;} public class DependentBean {public String dosomething () {return "hello:";}@autowiredPrivate Test;} XML -Konfiguration
<bean id = "test"> <Eigenschaft name = "abhängigbean"> <bean> </bean> </property> <Eigenschaft name = "name" value = "zlx"> </property> </bean>
Die MyFactoryBean -Funktion der Werksbean besteht darin, die Testklasse zu wickeln. Stellen Sie zunächst Eigenschaften für MyFactoryBean fest, erstellen Sie dann eine Testinstanz in der Nachpropertie -Methode der MyFactoryBean und setzen Sie die Eigenschaften. Das Instantieren von MyFactoryBean wird schließlich die GetObject -Methode aufrufen, um das erstellte Testobjekt zurückzugeben. Hier hängt MyFactoryBean von Depentbean ab, und abhängigbean selbst hängt vom Test ab. Dies ist also eine kreisförmige Abhängigkeit
prüfen:
public class testcircle2 {private endgültige statische classPathxMlApplicationContext moduleContext; test = (test) moduleContext.getbean ("test");} public static void main (String [] args) {System.out.println (test.name);}}Ergebnis:
Verursacht durch: org.springframework.bean.factory.beancreationException: Fehler erstellen Bean mit dem Namen 'com.alibaba.test.circle.Dependentbean#1C701A27': AutoWiring of Fields fehlgeschlagen; Eine verschachtelte Ausnahme ist org.springframework.bean.factory.beancreationException: konnte nicht automatisch field: private com.alibaba.test.circle.test com.alibaba.test.circle.dependentbean.test; Verschachtelte Ausnahme ist org.springframework.bean.factory.beancurentincreationException: Fehler erstellen Bean mit Name 'Test': FactoryBean, das derzeit in der Erstellung von GetObject zurückgegeben wird
3.2 Analyse der Gründe
Beim Instantiieren von Test wird getBean(“test”) ausgelöst, und es wird festgestellt, ob die aktuelle Bohne existiert
Wenn es nicht existiert, erstellen Sie eine Testinstanz. Nach der Erstellung werden die aktuellen Bohneninformationen in der SingletonFactores-Einteilungskarte platziert.
Injizieren Sie dann die Attributabhängige in die Instanz. Wenn die Attributinjektion verwendet wird, wird getBean(“depentBean”) verwendet.
Wenn Sie feststellen, dass die Abhängigkeit nicht existiert, werden Sie die Abhängigkeit so instanziieren und dann in SingletonFactores einfügen.
Dann automatisierte Injektionstest und dann getBean(“test”); Zu diesem Zeitpunkt (1) gibt Getingleton den sofortigen Test zurück. Da der Test eine Fabrikbohne ist, return test.getObject();
MyFactoryBeans After PropertieStieStet wurde noch nicht berufen, also test.getObject() kehrt null zurück.
Im Folgenden finden Sie den folgenden Prozess der Erstellung von Frühlingsbohnen:
getBean ()-> Instanz-> Autoweged-> Eigenschafts-> Nachpropertiesset setzen
Das heißt, das Aufrufen der GetObject -Methode wurde früher als die NachpropertieStet -Methode aufgerufen.
Dann ändern wir MyFactoryBean so wie folgt:
öffentliches Objekt getObject () löst Ausnahme aus {// Todo automatisch generierte Methode stubif (null == test) {AfterPertieSt ();} return test;} public void AfterPertieStieSet () löst eine Ausnahme aus {if (null == test) {System.out.println ("Name:" + this.name); Test = neuer Test (); test.name = abhängigbean.dosomething () + this.name;}} Das heißt, wenn Sie zuerst in GetObject beurteilen, ist es besser, test==null Rufen Sie dann After Propertiesset an, und wenn test==null eine Testinstanz in After PropertieStieStet erstellt, sieht es gut aus, und ich möchte unser Problem wirklich lösen. Tatsächlich funktioniert es jedoch immer noch nicht, da nach der Nachischinterität abhängig und zu diesem Zeitpunkt depentBean=null .
3.3 darüber nachdenken, wie man es löst
3.2 Analyse Grund ist, dass die MyFactoryBean erstmals erstellt wurde und die Depentbean während des Erstellens der MyFactoryBean erstellt wurde. Beim Erstellen der Depentbean ist eine Instanz der automatischen MyFactoryBean erforderlich. Anschließend wird die GetObject -Methode aufgerufen, bevor sie nach der Propertiesset aufgerufen werden, sodass NULL zurückgegeben wird.
Wenn Sie also zuerst eine Depentbean erstellen und dann eine MyFactoryBean erstellen? Die folgende Analyse wird durchgeführt:
Erstens wird die Depentbean instanziiert und zu SingletonFactores hinzugefügt
Die Depentbean -Instanz wird den Test automatisiert, sodass die Testinstanz zuerst erstellt wird.
Erstellen Sie eine Testinstanz und schließen Sie sich den Singletonfactores bei
Die Testinstanz injiziert die Depentbean -Instanz bei Attributen, sodass sie getBean(“depentBean”);
getBean(“depentBean”) stellt fest, dass es in SingletonFactores bereits eine Abhängigkeit gibt und das abhängige Objekt zurückgibt
Da Abhängigkeit nicht eine Fabrikbohne ist, gibt es direkt abhängige Bohnen zurück
Die Testinstanz wird erfolgreich in die Depentbean -Instanz injiziert, Testinstanzinitialisierung OK
Depentbean -Instanz Autoweged -Testinstanz OK
Nach dieser Analyse ist es möglich, zuerst eine Depentbean zu erstellen und dann die MyFactoryBean zu instanziieren. Ändern Sie den XML in Folgendes:
<bean id = "abhängigBean"> </bean> <bean id = "test"> <Eigenschaft name = "abhängigBean"> <ref bean = "abhängigBean"/> </property> <Eigenschaft name = "name" value = "zlx"> </property> </bean>
TEST RUN ERGEBNISSE:
Name: ZLX
Hallo: Zlx
Wenn es wirklich in Ordnung ist, dann wird nach dieser Analyse die obige XML -Konfiguration angepasst, die definitiv einen Fehler macht, da der Test früher als die Abhängigkeit erstellt wurde, und dies ist nach dem Test wahr. Darüber hinaus kann man sich vorstellen, dass eine Fabrikbohne sich auf eine Fabrikbohne stützt, die unabhängig von der Erklärung der Erklärung unweigerlich scheitert.
3.3 Ein Gedanke
Das obige injiziert zuerst die Abhängigkeit, die in MyFactoryBean verwendet werden muss, und injiziert dann die MyFactoryBean, und das Problem wird gelöst. Wenn Sie also das erstellte Objekt mit ID = "Test" in einer anderen Bean verwenden müssen, wie sollte diese Bean injiziert werden?
Wird es in ähnlicher Weise erfolgreich sein? Lassen Sie es für alle denken ^^
öffentliche Klasse usetest {@autowiredPrivate Test;}<bean id = "usetest"> </bean> <bean id = "abhängigBean"> </bean> <bean id = "test"> <Eigenschaft name = "abhängigBean"> <ref bean = "abhängigbean"/> </property> <Property name = "name" value = "zlx"> </</</leer>
4. Zusammenfassung
Wenn gewöhnliche Bohnen voneinander abhängig sind, ist die Reihenfolge der Bohneninjektion nicht miteinander verbunden, aber wenn Fabrikbohnen und gewöhnliche Bohnen voneinander abhängig sind, muss die gewöhnliche Bohne zuerst instanziiert werden. Dies liegt an der Besonderheit von Fabrikbohnen, dh eine GetObject -Methode.
Okay, das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.