プロトタイプビーンロード処理
前の記事では、全体のロードプロセスのシングルトンビーン非遅延ロードを分析し、非ビーン遅延ロードの一つのケースに加えて、春には道の定義を見て、豆は豆のプロトタイプ(試作品)でもあります:
1 26 7 8 9
一般的に、プロトタイプビーンのロード処理を話すと、ほぼ単一例豆は、doGetBeanの方法AbstractBeanFactoryのこの段階では、違いを見て:
それ以外の場合は1(mbd.isPrototype()){// 2それはプロトタイプだ- >新しいインスタンスを作成します。 3オブジェクトprototypeInstance = NULL; 4試行{5 beforePrototypeCreation(のbeanName)。 6 prototypeInstance =たcreateBean(のbeanName、MBD、引数)。7} 8最後に{9 afterPrototypeCreation(のbeanName)。10} 11 Beanは= getObjectForBeanInstance(prototypeInstance、名前、のbeanNameは、MBD)。12}
6行したcreateBeanは、主な違いは、直接Beanを作成している6行目にあるプロトタイプビーンのインスタンス化と同じで、シングルトンBeanは、私たちは、比較してみましょう:
1(mbd.isSingleton()){2 sharedInstance = getSingleton(のbeanName、新規のObjectFactory(){3パブリックオブジェクトGetObjectが()BeansException {4のtry {5リターンたcreateBean(のbeanName、MBD、引数)をスローした場合、6} 7キャッチ( BeansExceptionの例){8 //明示的にシングルトンキャッシュからインスタンスを削除します。循環参照の解決を可能にするために、作成プロセスによって//熱心にそこに9を入れてきた可能性がある10 //も一時的な言及を受け取った任意の豆を削除します。豆。 11 destroySingleton(のbeanName); 12スローEX; 13} 14} 15}); 16豆= getObjectForBeanInstance(sharedInstance、名前、のbeanName、MBD)。17}
これは、優先順位は、BeanオブジェクトのsingletonObjectsへの直接のリターンがある場合、Beanは存在singletonObjectsからそれを取得しようとすることですgetSingtonを、しようとします。
次に、我々は、プロトタイプとの差が、コードライン5を見て、単一豆豆の実施形態は、さらに、ライン9を作成し、5行目を特徴とする作成することを参照してください。
1保護ボイドbeforePrototypeCreation(文字列のbeanName){2オブジェクトCURVAL = this.prototypesCurrentlyInCreation.get()。 3 IF(CURVAL == NULL){ 4 this.prototypesCurrentlyInCreation.set(のbeanName)。 5} そう6(CURVAL instanceofの文字列){7設定した場合beanNameSet =新しいHashSetの (2)。 8 beanNameSet.add((String)をCURVAL)。 9 beanNameSet.add(のbeanName)。10 this.prototypesCurrentlyInCreation.set(beanNameSet)。11} 12 {他の13セット beanNameSet =(設定 )CURVAL; 14 beanNameSet.add(のbeanName)。15} 16}
この主なポイントはどこへ行くか、現在のThreadLocalのBEANNAMEセットの作成前に置くBeanが、目的は同時に、複数のスレッドが同じBeanを作成していないことを確認することであるということです。その後行われたものを作成した後で豆という認識のコードの9行目で見て:
1保護ボイドafterPrototypeCreation(文字列のbeanName){2オブジェクトCURVAL = this.prototypesCurrentlyInCreation.get()。 3 IF(CURVAL instanceofの文字列){4 this.prototypesCurrentlyInCreation.remove(); 5} そう6(CURVAL instanceofのセット){7設定した場合beanNameSet =(設定 )CURVAL; 8 beanNameSet.remove(のbeanName)。 9 IF(beanNameSet.isEmpty()){10 this.prototypesCurrentlyInCreation.remove()。11} 12} 13}
まあ理解し、それが他のスレッドがBeanを作成できるように、削除現在のBeanを見ることです。コードの最初の11行は、Bean実装クラスがFactoryBeanのであるならば、実際のオブジェクトを取得するためのgetObject()メソッドを呼び出すことを意味し、読んでいません。
BYNAMEソースコードの実装
Autowire(自動アセンブリ)機能、自動組立および最も一般的で春有望な開発者がBYNAME byTypeこれら二つの属性です。オブジェクトは、注射のための自動組立を解決することを目的とするため
1であれば(mbd.getResolvedAutowireMode()== RootBeanDefinition.AUTOWIRE_BY_NAME || 2 mbd.getResolvedAutowireMode()== RootBeanDefinition.AUTOWIRE_BY_TYPE){3 MutablePropertyValues newPvs =新しいMutablePropertyValues(PVS)。4 5 //は、該当する場合、名前でautowireに基づいてプロパティ値を追加します。 6 IF(mbd.getResolvedAutowireMode()== RootBeanDefinition.AUTOWIRE_BY_NAME){7 autowireByName(のbeanName、MBD、BW、newPvs)。 8} 9 (該当する場合)10 //タイプによってautowireに基づくプロパティ値を追加します。 11 IF(mbd.getResolvedAutowireMode()== RootBeanDefinition.AUTOWIRE_BY_TYPE){12 autowireByType(のbeanName、MBD、BW、newPvs)。13} 14 15 PVSの=のnewPvs。16}
ライン13は、byType形態は、自動的byTypeアセンブリコードが実行されたか否かを判断する、〜11行目、8行目にライン6を参照してくださいBYNAMEフォーム、BYNAMEのオートワイヤリングコードを実行しているか否かを判定する。すべてのだから、最初は達成BYNAMEライン7上のコードを見て:
1保護ボイドautowireByName(2列のbeanNameは、AbstractBeanDefinitionはMBD、BeanWrapper BW、MutablePropertyValuesのPVS){ 3 4列[] propertyNamesの=のunsatisfiedNonSimpleProperties(MBD、BW)。(文字列プロパティ名:propertyNames)5 {6 IF(containsBean(プロパティ名)){7オブジェクトビーン= getBean(プロパティ名)。8 pvs.add(propertyNameの、豆)。 9 registerDependentBean(propertyNameの、のbeanName)。10 IF(logger.isDebugEnabled()){11 logger.debug(「Bean名から名前によって追加されたオートワイヤリング"+ +のbeanName 12 " 'プロパティ'を介して" +プロパティ名+ " 'という名前のBeanに'" +プロパティ名+ "'"); 13}そうでなければ14} 15 {16(logger.isTraceEnabled()){17 logger.trace( "オートワイヤリングていないプロパティ「" +プロパティ名+もし" '豆の"' +のbeanName + 18「」
スペースの問題、異なるコード、論理櫛の層を持ちます:
- 4行目、豆を見つけるには、オブジェクトがプロパティのプロパティタイプを見つけることであることを意味し、ビットの周りにこれらの単語の単純な属性プロパティではなく、オブジェクトのではないすべての種類は、このようなタイプのCharSequence、番号タイプ、日付型として、発見されます、 URLのタイプ、URIタイプ、ロケールタイプは、クラスタイプは無視され、々BeanUtilsの可視isSimpleProperty具体的な方法
- 図5に示すように、ライン - ビーン定義は、属性名、name属性対応するBeanの最初のインスタンスが含まれている場合は7行、すべての属性を通るが、発見されました
- 現在のBeanに登録9行目registerDependentBeanは、それは豆に依存する前に破壊される豆、最初の破壊のための豆を依存します
コードの残りの部分は、何も言うことは、プレイログの一部ではありません。
byTypeソースコードの実装
そのBYNAMEのソースコードを達成するために、上記の、のは、達成するためにbyTypeのソースコードを見てみましょう:
1保護ボイドautowireByType(2列のbeanNameは、AbstractBeanDefinitionはMBD、BeanWrapper BW、MutablePropertyValuesのPVS){ 3 4のTypeConverterコンバータ= getCustomTypeConverter()。5 IF(コンバータ== NULL){ 6変換器= BW。7} 8 9セットautowiredBeanNames =新しいLinkedHashSetの (4)。10文字列[] propertyNamesの=のunsatisfiedNonSimpleProperties(MBD、BW)。11(文字列プロパティ名:propertyNames){12のtry {13のPropertyDescriptor PD = bw.getPropertyDescriptor(プロパティ名)。14 // Object型用タイプでオートワイヤリングしようとしないでください:決してそれは技術的に満たされていない、非単純なプロパティである場合でも、15 //を意味がありません。 16 {17 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(PD)IF(Object.class.equals(pd.getPropertyType())!)。18 //は優先順位を付け、ポストプロセッサの場合、タイプマッチングのためのinit熱望しないようにしてください。 !熱心な19ブール= PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass()); 20 DependencyDescriptorのDESC =新しいAutowireByTypeDependencyDescriptor(methodParam、熱心)。21オブジェクトautowiredArgument = resolveDependency(DESC、のbeanName、autowiredBeanNames、コンバータ)。22 IF(!autowiredArgument = NULL){23 pvs.add(propertyNameの、autowiredArgument)。24}(文字列autowiredBeanName:autowiredBeanNames)25 {26 registerDependentBean(autowiredBeanName、のbeanName)。27 IF(logger.isDebugEnabled()){28 logger.debug( "オートワイヤリングBean名からタイプ別「" +のbeanName + " '' プロパティを介して、" + +)+ autowiredBeanName + "'" " 'という名前のBeanへ'" 29プロパティ名。30} 31} 32 autowiredBeanNames.clear()。33} 34} 35キャッチ(BeansExceptionのEX){36投新しいUnsatisfiedDependencyException(mbd.getResourceDescription()、のbeanName、プロパティ名、EX)。37} 38} 39}
前と同じように、10は、ビーンプロパティで発見された行は、オブジェクト型属性です。
それは非単純なオブジェクトのプロパティであることも、技術的な観点から、意味がありません、自動的にオブジェクトの種類を組み立てるしようとしないでください:それは、プロパティ記述子がPropertyName意味を対応する取得、PropertyName意味を歩く審判のノートと対応する注記16行を取ることです。
ライン20を介してライン18は、(あまりに明らかではないがやっている)、byType実装方法resolveDependency線21の主な供給源は、メソッドがクラスDefaultListableBeanFactory AbstractAutowireCapableBeanFactoryのこのタイプを達成するための方法であって、スキップされます。
1パブリックオブジェクトresolveDependency(DependencyDescriptor記述子、文字列のbeanName、2セットautowiredBeanNames、にTypeConverterにTypeConverter)がBeansExceptionをスロー{3 4 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer())。 5(descriptor.getDependencyType()に等しい(でObjectFactory.class)){もし 6リターン新しいDependencyObjectFactory(記述子、のbeanName)。7} そう8 IF(descriptor.getDependencyType()に等しい(javaxInjectProviderClass)){9リターン新しいDependencyProviderFactory()createDependencyProvider(記述子、のbeanName)。他の10} 11 {12リターンdoResolveDependency(記述子、descriptor.getDependencyType()、のbeanName、autowiredBeanNames、にTypeConverter)。13} 14}
ここで私は自動的にどのような性質を決定するために必要でObjectFactory.classアセンブリまたはjavaxInjectProviderClassか、私たちは12を達成するためのコード行を見て、他の組み立てている他は、次のとおりです。
1保護されたオブジェクトdoResolveDependency(DependencyDescriptor記述子、クラス タイプ、文字列のbeanName、2セットautowiredBeanNames、にTypeConverterにTypeConverter)がBeansExceptionをスロー{3 4 Object値= getAutowireCandidateResolver()getSuggestedValue(記述子)。5 IF(!値= NULL){ 6場合(文字列のinstanceof値){7列strVal = resolveEmbeddedValue((文字列)値)。8 BeanDefinition BD =(のbeanName = NULL && containsBean(のbeanName)getMergedBeanDefinition(のbeanName):!?NULL); 9値= evaluateBeanDefinitionString(strVal、BD)。10} 11のTypeConverterコンバータ=(!?のTypeConverter = NULLにTypeConverter:getTypeConverter()); 12戻りconverter.convertIfNecessary(値、タイプ)。13} 14 15もしそうでなければ(type.isArray()){16 ... 17} 18 IF(Collection.class.isAssignableFrom(タイプ)&& type.isInterface())他{19 ... 20} 21 Map.class(もし。他isAssignableFrom(タイプ)&& type.isInterface()){22 ... 23} 24 {25地図 matchingBeans = findAutowireCandidates(のbeanName、タイプ、記述子); 26 IF(matchingBeans.isEmpty()){27 IF(descriptor.isRequired()){28 raiseNoSuchBeanDefinitionException(タイプ、 ""、記述子); 29} 30リターンヌル。31} 32(matchingBeans.size()> 1){33列primaryBeanName = determinePrimaryCandidate(matchingBeans、ディスクリプタ)であれば、34(primaryBeanName == NULL){35投新しいNoSuchBeanDefinitionException(タイプは、 "単一マッチングBeanを期待が、見つかった" IF + 36 matchingBeans.size()+ ":" + matchingBeans.keySet())。37} 38 IF(autowiredBeanNames = NULL!){39 autowiredBeanNames.add(primaryBeanName)。40} 41リターンmatchingBeans.get(primaryBeanName)。42} 43 //私たちは、正確に一つの試合を持っています。 44のMap.Entry 。エントリー= matchingBeans.entrySet()イテレータ()次の()。45 IF(!autowiredBeanNames = NULL){46 autowiredBeanNames.add(entry.getKey())。47} 48リターンentry.getValue()。49} 50}
結果は省略されているコード配列のアセンブリ、コレクションアセンブリコードマップアセンブリを簡素化するために、読んでいない四行目のヌル、組立性に重点を置い普通の外観です。最初の行25人の候補者は、自動組立で取得します。
1つの保護された地図findAutowireCandidates(2列のbeanName、クラスrequiredType、DependencyDescriptor記述子){ 3 4列[] candidateNamesの= BeanFactoryUtils.beanNamesForTypeIncludingAncestors(5本、requiredType、真、descriptor.isEager())。 6地図 結果=新しいのLinkedHashMap (candidateNames.length)。 7(クラスautowiringType:this.resolvableDependencies.keySet()){ 8 IF(autowiringType.isAssignableFrom(requiredType)){9オブジェクトautowiringValue = this.resolvableDependencies.get(autowiringType)。10 autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue、requiredType)。11 IF(requiredType.isInstance(autowiringValue)){12 result.put(ObjectUtils.identityToString(autowiringValue)、autowiringValue)。13ブレーク; 14} 15} 16} 17のための(文字列candidateName:candidateNames){18 IF(!candidateName.equals(のbeanName)&& isAutowireCandidate(candidateName、記述子)){19 result.put(candidateName、getBean(candidateName))。20} 21} 22リターン結果。23}
整理するためにコードのロジック:
- 型Bean実装クラスまたはサブクラス指定された定義のすべてを見ているgetBeanNamesForType DefaultListableBeanFactory法により、第1の取得候補Bean名
- 自動組立のライン16の横型判定ライン7が自動的に正しい形で組み立てられるべきではなく、Beanの操作のいくつかの非遅延ロード初期化する単一の実施形態の前後[解析春源]があるときテキストPrepareBeanFactory方法私は自動的に組み立てられるタイプは、ResourceLoaderとして正しいタイプである場合、具体的方法AutowireUtils.resolveAutowiringValueライン10の実装を見て、タイプのためのプロキシ・インスタンスを生成する、前に述べました
- 通常、コードは17であり、ライン21 - ラインがあれば、デフォルトは、判定は、自動組立のための候補ではないBeanDefinitionのbeanNameに応じて決定されているものを見つけるために、1つずつ実行しました
autowire候補属性がfalseに設定されていません
このように、地図を形成するために組み立てられるすべての目的を達成するために候補クラスまたはサブクラスを取得するには、キーのbeanName、バリュー具体的な豆です。そして、取得ビーン後のロジックを振り返ります:
1つの地図matchingBeans = findAutowireCandidates(のbeanName、タイプ、記述子); 2 IF(matchingBeans.isEmpty()){3 IF(descriptor.isRequired()){4 raiseNoSuchBeanDefinitionException(タイプ、 ""、記述子); 5} 6戻りヌル。 7} 8 IF(matchingBeans.size()> 1){ 9列primaryBeanName = determinePrimaryCandidate(matchingBeans、記述子); 10(primaryBeanName == NULL){11投新しいNoSuchBeanDefinitionException(タイプは、 "単一マッチングBeanを期待が、見つかった" IF + 12 matchingBeans.size()+ ":" + matchingBeans.keySet())。13} 14 IF(autowiredBeanNames = NULL!){15 autowiredBeanNames.add(primaryBeanName)。16} 17リターンmatchingBeans.get(primaryBeanName)。18} 19 //私たちは、正確に一つの試合を持っています。 20のMap.Entry 。エントリー= matchingBeans.entrySet()イテレータ()次の()。21 IF(!autowiredBeanNames = NULL){22 autowiredBeanNames.add(entry.getKey())。23} 24 ... 25}
ロジックを整理:
- あなたが得る場合はマップが空で、プロパティを注射しなければならない、例外
- 地図に複数の候補を取得する場合、それはどうかが判断されます
設定属性が「true =プライマリ」で、コード実行の13行があるライン15に〜を取った、第一の方法は、8つのリターン空行でない、説明が春を多く使用すると信じていること例外をスローもっと身近な - あなたは地図は一候補である取得する場合は、直接それを取ります
この方法によって、全体のプロセスはbyType自動組立を達成するために、自動組立工程byType長く、より多くの中間の詳細は、また、それを把握するために見てする必要があります。
> PropertyValueをマッピングした後、単にMutablePropertyValuesはメソッドAbstractPropertyAccessor setPropertyValuesクラスと1回の注射により1最後のトラバースを得る配置されている - 最後にすべてのことがPropertyName意味が注入されることに注意してください。
FactoryBeanの通過を達成するために、ソースコードの豆例をゲット
私たちは、それがビーンのカスタマイズプロセスを達成するためのgetObject()メソッドを書き換え、この部分は、我々は春のソースがFactoryBeanののBeanインスタンスを取得することによって達成されるかを見ていきますFactoryBeanのインタフェースによって達成することができます知っています。DoGetBeanコードを直接AbstractBeanFactoryビーンこのセクションの方法の単一の例を作成配置されています。
1 // Beanのインスタンスを作成します。 2(mbd.isSingleton()){3 sharedInstance = getSingleton(のbeanName、新規のObjectFactory(){4パブリックオブジェクトGetObjectが()BeansException {5試み{6リターンたcreateBean(のbeanName、MBD、引数)をスローした場合、7} 8キャッチ( BeansExceptionの例){9 //明示的にシングルトンキャッシュからインスタンスを削除します。循環参照の解決を可能にするために、作成プロセスによって//熱心にそこに10を入れてきた可能性がある11 //も一時的な言及を受け取った任意の豆を削除します。豆。 12 destroySingleton(のbeanName); 13スローEX; 14} 15} 16}); 17豆= getObjectForBeanInstance(sharedInstance、名前、のbeanName、MBD)。18}
このコードは言わないであろう前に分析線、 - FactoryBeanの最初ののgetObject()メソッドを呼び出し、Beanが対象であることがインスタンス化され、それはコード3、行16を実行する後にすることです。17行目のメソッドの実行後:
1保護されたオブジェクトgetObjectForBeanInstance(2オブジェクトbeanInstance、文字列名、文字列のbeanNameは、RootBeanDefinitionはMBD){ 3 4 // Beanが工場でない場合、工場出荷時の逆参照コードトライを呼び出してはいけません。 5(BeanFactoryUtils.isFactoryDereference(名)&&(beanInstance instanceofはFactoryBeanの)!){6スロー新しいBeanIsNotAFactoryException場合(transformedBeanName(名)、beanInstance.getClass()); 7} 8 9 //今は通常BeanまたはFactoryBeanのであってもよい、Beanインスタンスを持っています。10 //それはFactoryBeanのなら11 //呼び出し側が実際に工場への参照を望んでいない限り、我々は、Beanインスタンスを作成するためにそれを使用します。 12 {13リターンbeanInstance((beanInstanceのinstanceof FactoryBeanの)|| BeanFactoryUtils.isFactoryDereference(名前)!)であれば、14} 15 16オブジェクトオブジェクト= NULL; 17 IF(MBD == NULL){18物体= getCachedObjectForFactoryBean(のbeanName)。19} 20工場(オブジェクト== NULL){21 //戻りBeanインスタンス場合。 22 FactoryBeanの工場=(FactoryBeanの)beanInstance。それはシングルトンである場合FactoryBeanのから取得した23 //キャッシュオブジェクト。 24 IF(MBD == NULL && containsBeanDefinition(のbeanName)){25のMBD = getMergedLocalBeanDefinition(のbeanName)。26} 27ブール合成は=(MBD = NULL && mbd.isSynthetic()!)。28オブジェクト= getObjectFromFactoryBean(工場、のbeanName、合成!)。29} 30リターンオブジェクト。31}
5行目7のbeanNameへの最初の行は、「&」Bean定義FactoryBeanののBEANNAME機能の実装クラスの始まりであるため、「&」実装クラスではなくFactoryBeanの、スロー例外の冒頭で、満足していないかを判断します。
次の場合、ライン - そして、12行14を決定
- Bean実装クラスはFactoryBeanのではありません
- 先頭に「&」をBEANNAME
直接返すようにBeanオブジェクトを生成し、両方の場合において、プロセスの残りの部分は実行されません。
最後に、プロセスは、カスタマイズ豆を達成するために、30行までのgetObject()メソッドへの最終呼び出しを16番目に行ったライン28個の方法で最初に行わ。
同期1つの保護オブジェクトgetObjectFromFactoryBean(FactoryBeanの工場、文字列のbeanName、ブールshouldPostProcess){2 IF(factory.isSingleton()&& containsSingleton(のbeanName)){3(getSingletonMutex()){4 Objectオブジェクト= this.factoryBeanObjectCache.get(のbeanName) ; 5 IF(オブジェクト== NULL){ 6物体= doGetObjectFromFactoryBean(工場、のbeanName、shouldPostProcess)。7 this.factoryBeanObjectCache.put(のbeanName、(対象= nullオブジェクト:!?NULL_OBJECT)); 8} 9リターン(オブジェクト= NULL_OBJECTオブジェクト:!?NULL); 他の10} 11} 12 {13リターンdoGetObjectFromFactoryBean(工場、のbeanName、shouldPostProcess)。14} 15}
コード〜コード、ライン13、ライン12、最終的に最初の行の11行は、次の段落の呼び出し、同じです。
1つのプライベートオブジェクトdoGetObjectFromFactoryBean(2最終FactoryBeanの工場は、最終的な文字列のbeanName、最終ブールshouldPostProcess)3 BeanCreationException {4スロー 5オブジェクトのオブジェクトと、 6トライ{7 IF(System.getSecurityManager()!= NULL){ 8のAccessControlContext ACC = getAccessControlContext()。9トライ{10物体= AccessController.doPrivilegedの(新しいたPrivilegedExceptionAction