この記事では、Spring IOCコンテナの依存噴射原則に関する簡単な議論を紹介し、次のようにそれを共有します。
IOCコンテナの初期化の主なタスクは、IOCコンテナにビアンデフィニッションデータマップを確立することです。 IOCコンテナがBean依存関係の関係を注入するのを見ませんでした。
現在のIOCコンテナがユーザー定義のBean情報をロードしていると仮定すると、依存関係は主に2つの段階で発生します。
通常の状況では、ユーザーが初めてIOCコンテナから豆を要求するとトリガーされます。
ただし、beandefinition情報の怠zyinit属性を制御して、コンテナが豆を事前にインストールできるようにすることができます。つまり、特定の豆の依存噴射プロセスが初期化プロセス中に完了します。
1。getBeanによってトリガーされた依存性噴射
基本的なIOCコンテナインターフェイスBeanFactoryには、GetBeanのインターフェイス定義があります。このインターフェイスの実装は、トリガー依存性噴射が発生する場所です。依存関係注入のプロセスをさらに理解するために、Base Class AbstractBeanFactoryのDefaultListableBeanFactoryから始めて、GetBeanの実装を見てみましょう
//ここにBeanFactoryインターフェイスの実装があります。たとえば、GetBeanインターフェイスメソッドなど。 } @Override public <t> t getBean(string name、class <t> rebynytype)throws beansexception {return dogetbean(name、rebynettype、null、false); } @Override public Object getBean(String name、object ... args)throws beansexception {return dogetbean(name、null、args、false); } public <t> t getBean(string name、class <t> requiredtype、object ... args)throws beansexception {return dogetbean(name、rebynecttype、args、false); } //これは、Beanが実際に取得される場所、つまり、依存関係注入が@SuppressWarnings( "Unchecked")がトリガーされる場所です。オブジェクトビーン; //手動で登録されたシングルトンのシングルトンキャッシュを熱心に確認します。 //手動で登録されたシングルトンのシングルトンキャッシュを熱心に確認します。 //手動登録のシングルトンキャッシュを熱心にチェックしてくださいシングルトン//最初にキャッシュから豆を取得し、作成されたシングルトンビーンズを処理します。オブジェクトSharedInstance = GetSingleTon(BeanName)を繰り返し作成しないでください。 if(sharedInstance!= null && args == null){if(logger.isdebugenabled()){if(issingletoncurllyningincreation(beanname)){ogger.debug( "熱心にキャッシュされたインスタンスのシングルトンbean ' + benname +" } else {logger.debug( "singleton beanのキャッシュされたインスタンスを返す '" + beanname + "'"); }} // getobjectforbeaninstanceは、ファクトリビーンの関連する処理を取得して、工場出荷時の生産結果を得るために、工場の関連処理を完了します。 BeanFactoryとFactoryBeanの違いが前に言及されています。このプロセスは、後で詳細に分析されます。 = getObjectforBeanInstance(SharedInstance、name、beanname、null); } else {//このbeanインスタンスをすでに作成している場合、失敗します://円形の参照内で想定されます。 if(isprotopecurlynelyincreation(beanname)){beancurlentyincreationexception(beanname); } // // IOCコンテナ内のビーンデファイニングが存在するかどうかを確認します。現在の工場に存在しない場合は、親BeanFactoryチェーンに従って、BeanFactory ParentBeanFactory = getParentBeanFactory()を上に調べます。 if(parentbeanfactory!= null &&!containsbeandefinition(beanname)){//見つかりません - >親をチェックします。 string nametolookup = originalbeanname(name); if(args!= null){//明示的なargsを持つ親への委任。 return(t)parentbeanfactory.getBean(nametolookup、args); } else {// argsなし - >標準のgetbeanメソッドに委任します。 return parentbeanfactory.getBean(nametolookup、rebyttype); }} if(!typecheckonly){markbeanascreated(beanname); } try {// beandefinition final rootbeandefinition mbd = getMergedLocalBeanDefinition(beanName); CheckMergedBeanDefinition(MBD、BeanName、Args); //現在の豆が依存している豆の初期化を保証します。 //現在の豆が(もしあれば)string [] depenson = mbd.getdependson()に依存するすべての豆を再帰的に取得します。 if(depenentson!= null){for(string dep:dependson){if(isdependent(beanname、dep)){throw new beancreationexception(mbd.getResourcedesscription()、beanName、 " } RegisterDependentBean(dep、beanname); getbean(dep); }} // createbeanメソッドを呼び出してシングルトンビーンインスタンスを作成するif(mbd.issingleton()){sharedInstance = getsingleton(beanname、new objectactory <object>(){@override public object getobject()throws beansexcection {try {return createbean(beanname(beans); // Singleton Cacheからのインスタンスを削除してください。 bean = getobjectforbeaninstance(sharedinstance、name、beanname、mbd); } //これは、プロトタイプBeanを作成する場所です。オブジェクトprototypeinstance = null; try {beforeprototypeCreation(beanname); prototypeinstance = createbean(beanname、mbd、args); }最後に{afthprototypecreation(beanname); } bean = getobjectforbeaninstance(prototypeinstance、name、beanname、mbd); } else {string scopename = mbd.getScope();最終スコープスコープ= this.scopes.get(scopename); if(scope == null){新しいIllegalStateException( "スコープ名に登録されているスコープなし '" + scopename + "'"); } try {object scopedInstance = scope.get(beanname、new objectFactory <object>(){@Override public object getobject()throws beansexception {beforeprototypecreation(beanname); try {return createbean(beanname、mbd、args); bean = getobjectforbeaninstance(scopedinstance、name、beanname、mbd); } catch(IllegalStateException ex){新しいbeancreationException(beanname、 "scope '" + scopename + "'は現在のスレッドではアクティブではありません。シングルトンから参照する場合は、この豆のスコーププロキシを定義する「 +」を検討してください。 }}} catch(beansexception ex){cleanupafterbeancreationfailure(beanname); Exを投げる; }} //必要なタイプの場合は、実際のBeanインスタンスのタイプと一致します。 //作成されたBeanでタイプチェックが実行されます。問題がない場合、新しく作成された豆が返されます。この豆は、依存関係を含むbeanです。 } catch(typemismatchException ex){if(logger.isdebugenabled()){logger.debug( "bean '" + name + "' ''" + classutils.getQualifiedName(requiredtype) + "''"、ex); }新しいbeannotOfRequiredTypeexception(name、requiredType、bean.getClass())を投げる; }} return(t)bean; }ここでは、依存関係の注入がトリガーされます。依存関係注射は、コンテナ内のビアンデフィニッションデータが確立されたときに発生します。 IOCコンテナを最も簡単な方法で説明することはできますが、つまり、ハッシュマップとして扱うことはできますが、このハッシュマップはIOCコンテナ全体ではなく、コンテナの最も基本的なデータ構造であるとしか言えません。
この依存性注入プロセスについては、以下で詳しく説明します。図1.1は、依存噴射の一般的なプロセスを示しています。
図1.1依存性噴射プロセス
GetBeanは、依存関係噴射の出発点です。その後、beandefinition、Bean Post-processorなどのinit-method属性定義を実装するなど、必要な豆を生産するためにabstractautowirecapablebeanfactoryのcreatebeanが呼び出され、Beanの初期化も処理されます。
@OverrideプロテクションオブジェクトCreateBean(String BeanName、rootBeanDefinition MBD、Object [] Args)Throws BeanCreationException {if(ogger.isdebugenabled()){oggger.debug( "Bean '" + beanname + "' '' '' '' '' '' '' '' '' '' + beanname +" '' ''の作成} rootbeandefinition mbdtouse = mbd; //この時点でBeanクラスが実際に解決されていることを確認し、//共有マージされたBean定義に保存できない動的に解決されたクラスの場合、Bean定義をクローンします。 //ここで、作成する豆をインスタンス化できるかどうか、このクラスをクラスローダークラス<?> ResolveBeanClass(MBD、BeanName)を介してロードできるかどうかを判断します。 if(ResolvedClass!= null &&!mbd.hasbeanclass()&& mbd.getbeanclassname()!= null){mbdtouse = new rootbeanDefinition(MBD); mbdtouse.setbeanclass(ResolvedClass); } //メソッドオーバーライドを準備します。 try {mbdtouse.preparemethodoverrides(); } catch(beandefinitionValidationException ex){新しいbeandefinitionStoreException(mbdtouse.getResourcedEscription()、beanName、 "メソッドオーバーライドの検証が失敗しました"、ex); } try {// beanpostprocessorsにターゲットビーンインスタンスの代わりにプロキシを返す機会を与えます。 // BeanがPostprocessorを構成している場合、返されたプロキシオブジェクトBean = ResolveBeForeInstantiation(BeanName、MBDTouse); if(bean!= null){return bean; }} catch(throwable ex){新しいbeancreationexception(mbdtouse.getResourcedescription()、beanName、 "Beanのインスタンス化前のbeanpostprocessor"、ex); } try {object beaninstance = docreatebean(beanname、mbdtouse、args); if(logger.isdebugenabled()){logger.debug( "beanのインスタンスの作成が終了した" + beanname + "'"); } return beaninstance; } catch(beancreationException ex){//適切なBean作成コンテキストを使用して以前に検出された例外がすでに... Exを投げます。 } catch(暗黙のうちに印象的なものを描く){// defaultsingletonbeanregistryに通信するIllegalStateException ... show ex; } catch(throwable ex){新しいbeancreationexception(mbdtouse.getResourcedescription()、beanName、「Bean Creation on Bean Creation oneming Expention」、ex); }} // beansが生成されたオブジェクトの生成方法を確認するためにドクリートの隣にあるducreatebean(最終的な文字列beanname、final rootbeandefinition mbd、final object [] args){//豆をインスタンス化します。 //作成されたBean Object BeanWrapper InstanceWrapper = nullを保持するために使用されます。 //シングルトンの場合、最初にキャッシュ内の同じ名前の豆をクリアするif(mbd.issingleton()){instancewrapper = this.factorybeaninstancachache.remove(beanname); } //これはBeanを作成する場所であり、(InstanceWrapper == null){// createbeaninstanceによって行われます{//:工場メソッド、コンストラクター自動噴射、単純初期化インスタンスワッパー= createbeaninstance(beanname、mbd、args)など、対応する戦略を使用して指定された豆を作成します。 } final object bean =(instancewrapper!= null?instancewrapper.getWrappingInstance():null); class <? //ポストプロセッサがマージされた豆の定義を変更できるようにします。同期(mbd.postprocessinglock){if(!mbd.postprocessed){applymergedbeandefinitionPostprocessors(MBD、BeanType、BeanName); mbd.postprocessed = true; }} // cacheシングルトンは、cache cache cache cach beanfactoryawareのようなライフサイクルインターフェイスによってトリガーされた場合でも、循環参照を解決できます。 //事前に露出する必要がありますか:シングルトン&環状依存関係を許可し、現在の豆が作成されています。 if(earlysingletonexposure){if(logger.isdebugenabled()){ogger.debug( "eatelly caching bean '" + beanname + "'潜在的な円形参照を解決できる"); } //サイクル後期の依存関係を回避するために、Beanの初期化が完了する前に、インスタンスを作成するオブジェクトファクトリーを工場に追加できます。 addsingletonFactory(beanName、new objectFactory <Object>(){@Override public object getObject()Throws BeanSexception {// beans beanspostprocessorを使用して、再び豆への参照に頼っています。 getearlybeanReference(beanname、mbd、bean)}); } // Beanインスタンスを初期化します。 //これは豆の初期化であり、依存関係の注入はここでしばしば発生します。この露出したオブジェクトは、初期化が処理された後に豆として戻ってきたことを後悔しています。オブジェクトExposedObject = Bean; {//豆を入れて、各属性値を注入してください。その中で、他の豆に依存する属性があるかもしれませんが、依存性豆は再帰的に再帰的に摂取されます(beanname、MBD、InstanceWrapper)。 if(exposedObject!= null){// init-method exposedObject = initializeBean(beanName、exposedObject、MBD)などの初期化メソッドを呼び出す; }} catch(throwable ex){if(ex instance of beancreationexception && beanname.equals(((beancreationexception)ex).getbeanname())){thro(beancreationexception)ex; } else {throw beancreationException(mbd.getResourcedescription()、beanName、 "Bean Failed"、ex); }} if(areysingletonexposure){object ertysingletonreference = getsingleton(beanname、false); // EarlySingleTonReferenceは、円形依存関係が検出された場合にのみ空ではありません(areysingletonReference!= null){if(exposedObject == bean){//初期化方法でexposedObjectが変更されていない場合、exposedObject = erilysingletonReference; } else if(!this.allowrawinjectiondespitewrapping && hasdependentbean(beanname)){string [] depententbeans = getDependentBeans(beanName); Set <string>実際のdependentBeans = new LinkedHashset <String>(DependentBeans.Length); for(String DependentBean:DependentBeans){//検出依存関係if(!RemoseSingLetonifCreatedFutyPecheChonly(depententBean)){eachedDependentBeans.Add(depententBean); }} //豆が作成された後に依存する豆は作成されたに違いないため、実際の依存症は空ではありません。つまり、現在の豆が作成された後に依存する豆は作成されていないことを意味します。 「 ''他の豆に注入された[" + stringutils.collectiontocommadelimitedString(altualdependentbeans) +"]は、循環参照の一部として生バージョンで " +"ラップされました。たとえば、「AlloweAgerInit」フラグがオフになります。 "); }}}}} // beanを使い捨てとして登録します。 try {// scope registerdisposablebeanifn decessary(beanname、bean、mbd)に基づいてBeanを登録します。 } catch(beandefinitionValidationException ex){新しいbeancreationexception(mbd.getResourcedescription()、beanName、 "invalid destruction Signature"、ex); } exposedObjectを返します。 }依存関係注射には、実際には2つの主要なプロセスが含まれます
上記から、依存関係の噴射に特に密接に関連している方法が含まれることがわかります
CreateBeanInstance
豆に含まれるJavaオブジェクトを生成します
PopulateBean。
さまざまなBeanオブジェクトのプロパティを処理するプロセス(つまり、依存関係処理のプロセス)
最初にcreatebeaninstanceソースコードを見てみましょう
/** *適切なインスタンス戦略を使用して、指定されたBeanの新しいインスタンスを作成します。 * @param beanname beanの名前 * @param mbd bean bean args @param args ConstructorまたはFactory Method Invocationに使用する明示的な引数 * @return新しいインスタンスのBeanWrapper */保護されたBeanWrapper createbeaninstance(String beanname、rootbeandefinition mbd、clast ags aこの点。 //作成する豆のインスタンスのクラスがインスタンス化されることができることを確認します<? if(beanclass!= null &&!modifier.ispublic(beanclass.getModifiers())&&!mbd.isnonpublicaccesallowed()){Throw new beancreationexception(mbd.getResourcedescription()、beanname、 " }サプライヤー<? if(instancesupplier!= null){return gockainfromsupplier(instancesupplier、beanname); } //工場メソッドが空でない場合は、工場メソッド戦略を使用して、bean if(mbd.getFactorymethodname()!= null){return instantiate factorymethod(beanname、mbd、args); } //ショートカット同じ豆を再作成するとき... boolean resolved = false; Boolean autowiren deversional = false; if(args == null){synchronized(mbd.constructorargumentlock){//複数のコンストラクターには異なるパラメーターがあるため、コールする前に、(mbd.resolvedConstructororymethod!= null!= null! autowiren decessary = mbd.constructorarguments reSolved; }}} //解析された場合、解析されたコンストラクターメソッドを使用せずに再びロックせずに使用します(解決){//コンストラクターは自動的に自動的に注入します(beanname、mbd、null、null); } else {// default constructorを使用してコンストラクターInstantiatebean(beanname、mbd)をコンストラクターに使用します。 }} //コンストラクターを決定する必要があります... //コンストラクターコンストラクター<? if(ctors!= null || mbd.getResolvedautowireMode()== rootbeandefinition.autowire_constructor || mbd.hasconstructorargumentvalues()||!objectils.isempty(args)){return autowireconstror(runter autowireconstror(beanname、mbd、ctors、ctors、ctors、 } //特別な取り扱いなし:ARGノーコンストラクターを使用するだけです。 //デフォルトのコンストラクターを使用してBeanをインスタンス化します。 } /***デフォルトのコンストラクターを使用して、指定されたBeanをインスタンス化します。 * @param beanname beanの名前 * @param mbd bean bean for the BeanWrapper for the New Instance *///最も一般的なInstantiateBean保護されたBeanWrapper InstantiateBean(最終的な文字列BeanName、最終的なRootBeanDefinition MBD)デフォルトのインスタンス戦略は// cglibsubClassingInStantiationsTrategyです。つまり、CGLIBを使用してBeanをインスタンス化します。 {object beaninstance;最終的なBeanFactory Parent = this; if(system.getSecurityManager()!= null){beanInstance = accessController.dopriviledeged(new Priviledaction <object>(){@Override public object run(){return getInstantiationStrategy()。 } else {beanInstance = getInstantiationstrategy()。instantiate(mbd、beanname、parent); } beanwrapper bw = new beanwrapperimpl(beaninstance); initbeanwrapper(bw); BWを返します。 } catch(throwable ex){新しいbeancreationexception(mbd.getResourcedescription()、beanName、「bean failed」、ex); }}ここでは、Clibは豆をインスタンス化するために使用されます。 CGLIBは、ByteCodeジェネレーター用のクラスライブラリであり、Java Bytecodeを生成および変換する機能を提供する一連のAPIを提供します。
春のAOPでは、CGLIBはJava Bytecodeを強化するためにも使用されます。 IOCコンテナでは、CGLIBを使用してBeanオブジェクトを生成する方法を理解するには、SimpleInstantiationsTrategyクラスを確認する必要があります。 Beanオブジェクトを生成するためにSpringが使用するデフォルトのクラスです。 Beanオブジェクトをインスタンス化する2つの方法を提供します。
Public Class SimpleInstantiationsTrategyは、InstantiationsTrategy {@Override Public Object Instantiate(rootBeanDefinition BD、String BeanName、BeanFactory Owner){//オーバーライドがない場合はCGLIBでクラスをオーバーライドしないでください。 if(bd.getMethodoverrides()。isempty()){//ここで、BeanConstructor <?> constructortouseをインスタンス化するために指定されたコンストラクターまたは工場の方法を取得します。同期(bd.constructorargumentlock){constructortouse =(constructor <?>)bd.ResolvedConstructororFactoryMethod; if(constructortouse == null){final class <?> clazz = bd.getbeanclass(); if(clazz.isinterface()){new beaninstantiationexception(clazz、 "指定クラスはインターフェイス"); } try {if(system.getSecurityManager()!= null){constructutouse = accessController.dopriviledeged(new PrivileGedExceptionaction <constructor <?>>(){@Override public construstator <? } else {constructortouse = clazz.getDeclaredConstructor((class [])null); } bd.ResolvedConstructorOrFactoryMethod = constructortouse; } catch(throwable ex){新しいbeaninstantiationexception(clazz、 "デフォルトコンストラクターが見つかりません"、ex); }}} // beanutilsを介してインスタンス化します。このBeanutilsのインスタンス化は、コンストラクターを介してBeanをインスタンス化します。 beanutilsでは、特定のコールctor.newinstance(args)Return beanutils.instantiateclass(constructortuse)を確認できます。 } else {//オブジェクトをインスタンス化して、instantiatewithmethodinjection(bd、beanname、owner); }}}豆間の依存関係の処理
依存関係処理へのエントリは、上記のPopulateBeanメソッドです。関係する側面が多すぎるため、ここにコードを投稿しません。依存関係処理のプロセスの簡単な紹介:PopulateBeanメソッドでは、
まず、ビアンデファイニングでプロパティ値を設定してから、依存関係噴射プロセスを開始します。
まず、Autowire注入を処理して、bynameまたはbytype、次に属性が注入されます。
その後、Beanの参照を解析する必要があります。マネージャスト、ManagESET、ManageMapなどを解析した後、依存噴射の条件を準備しました。これは、実際にBeanオブジェクトを依存する別のBeanプロパティに設定し、処理されたプロパティはさまざまです。
依存性注入は、BeanWrapperのSetPropertyValuesで発生しますが、特定の完了はBeanWrapperサブクラスBeanWrapperimplに実装されます。アレイの注入、リストなどの収集クラスの注入、非収集クラスの注入など、Beanのプロパティ値の注入が完了します。
一連の注入の後、さまざまな豆の特性の依存噴射プロセスが完了します。
豆とオブジェクトの依存関係注入を作成する過程で、依存関係の注入は、ビアンデファイニングの情報に基づいて再帰的に完了する必要があります。
以前の再帰プロセスから、これらの再帰はすべてGetBeanでポータブルであることがわかります。
再帰は、必要な豆を見つけて、コンテキストシステムで豆に再帰的な呼び出しを作成することです。
別の再帰は、依存関係注射中にコンテナのgetBeanメソッドを再帰的に呼び出して、現在の豆の依存性豆を取得し、依存関係豆の作成と注入を引き起こすことです。
Beanの特性に依存関係注入を実行する場合、解析プロセスも再帰プロセスです。このようにして、依存関係によれば、現在の豆の作成が最終的に完了するまで、豆の作成と注入は層ごとに完了します。このトップレベルの豆の作成とその属性依存性噴射の完了により、現在の豆に関連する依存関係チェーン全体の噴射溶液が完了することを意味します。
Beanの作成と依存関係の注入が完了した後、依存関係によってリンクされた一連の豆がIOC容器に確立されます。この豆は、もはや単純なJavaオブジェクトではありません。 BeanシリーズとBeansの依存関係が確立された後、IOCの関連するインターフェイス方法を介して上位レベルのアプリケーションに非常に便利に使用できます。
2。怠zyinit属性と前インスタンス
以前の更新方法では、finishbeanfactoryInitializationが怠zyinitで構成された豆を処理するために呼び出されていることがわかります。
実際、この方法では、LazyInit属性の処理がカプセル化されており、実際の処理は、defaultListableBeanFactoryの基本コンテナの実施前のgingletlonメソッドで行われます。この方法では、事前に囲まれたシングルトンビーンズが完成し、この事前に象徴された完成は、実装するために容器に巧妙に委任されます。事前にインスタンスが必要な場合は、GetBeanをここで使用して依存関係の注入をトリガーします。通常の依存関係噴射トリガーと比較して、トリガー時間と機会は異なります。ここでは、コンテナの更新プロセス中、つまり、IOCコンテナがIOCコンテナがGetBeanを介して初期化された後に初めてBeanを要求する場合、通常の依存噴射とは異なり、IOCコンテナの初期化プロセス中に、依存性噴射が発生します。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。