春のソース(9)@Autowired注釈実装の原則(春豆自動組立

  実装@Autowiredノート、実際には、春の豆の自動組立工程。ソースコードを見て@Autowiredコメントセクションでは、我々は@Autowiredが実装AutowiredAnnotationBeanPostProcessorポストプロセッサによって達成されていることがわかります。
  
  図AutowiredAnnotationBeanPostProcessorクラス
  
  PriorityOrdered:ポストプロセッサAutowiredAnnotationBeanPostProcessor優先ことを確認し
  
  たBeanFactoryビーンコンテナによって直接取得することができるAutowiredAnnotationBeanPostProcessor:BeanFactoryAware
  
  BeanPostProcessor:ポストプロセッサは、初期化ビーン前と後に行わ
  
  InstantiationAwareBeanPostProcessor:豆は、インスタンス化の前後に配置され、豆プロパティ値のときに後処理を行う
  
  ビーンは、型コンストラクタビーンビーンなどの予測と確認として、インテリジェント・ポストプロセッサをインスタンス化:SmartInstantiationAwareBeanPostProcessorは。
  
  MergedBeanDefinitionPostProcessor:統合定義情報のビーン。
  
  私たちが最初にこれらのポストプロセッサの上に導入し、分析前に自動アセンブリ。
  
  はじめにポストプロセッサ
  
  BeanPostProcessor
  
  二つの方法BeanPostProcessor、postProcessBeforeInitializationとpostProcessAfterInitializationがあります。これらは、(例えばInitializingBean afterPropertiesSet法のinitメソッドの方法をカスタマイズする前または後に)、この時点で、豆のプロパティ値は、任意の豆初期化コールバックの前または後に完了充填された実行、およびBeanインスタンス我々が返す必要がある可能性がありさ元のインスタンスは、パッケージの種類です。このようなFactoryBeanのを返すように。
  
  InstantiationAwareBeanPostProcessor
  
  InstantiationAwareBeanPostProcessorはBeanPostProcessorインタフェースから継承されました。メインマルチは、次の3つの方法を提供します。
  
  postProcessBeforeInstantiation
  
  ターゲットオブジェクトを呼び出す前にあるビーン、ビーンが効果的にBeanのインスタンス化されるデフォルトのターゲットを防止するようにオブジェクトは、オブジェクトを委任することができます返さインスタンス化されます。
  
  オブジェクトresolveBeforeInstantiation保護(文字列のbeanName、RootBeanDefinition MBD){
  
  オブジェクトBean = nullは、
  
  (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved))IF {
  
  //確かBeanクラスを作成すると、AT実はこの点を解決しました。
  
  (!mbd.isSynthetic()&& hasInstantiationAwareBeanPostProcessors()){IF
  
  <?>クラスdetermineTargetTypeたtargetType =(のbeanName、MBD);
  
  IF(たtargetType = NULL!){
  
  豆= applyBeanPostProcessorsBeforeInstantiation(たtargetType、のbeanName);
  
  !IF(豆= NULL ){
  
  このメソッドがnull以外のオブジェクトを返す場合//、Beanは短絡時に作成されます。
  
  //さらにpostProcessAfterInitializationコールバックの構成BeanPostProcessorsからのみアプリケーション処理
  
  豆= applyBeanPostProcessorsAfterInitialization(豆、のbeanName)を、
  
  {保護オブジェクトapplyBeanPostProcessorsBeforeInstantiation(<?>クラスたbeanClass、文字列のbeanName)
  
  について(BeanPostProcessor BP:getBeanPostProcessors()){
  
  IF( InstantiationAwareBeanPostProcessor instanceofのBP){
  
  IBP = InstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor)BP;
  
  //は、Beanが観客の後処理方法の前に実行インスタンス
  
  オブジェクトibp.postProcessBeforeInstantiation結果=(たbeanClass、のbeanName);
  
  IF(結果= nullを!){
  
  戻り値の結果を、
  
  フォローアップを、我々は供給することができますこのメソッドがnull以外のオブジェクトを返す場合、参照、豆は、短絡時に作成されます。postProcessAfterInitializationコールバックの構成BeanPostProcessorsからのみさらに処理アプリケーション。
  
  postProcessAfterInstantiation
  
  方法は、(明示的または自動組立性を介して)充填された豆の特性が、スプリングをインスタンス化した後、コンストラクタ又はファクトリメソッドの動作を実行する前に発生しています。これは、自動組立を開始する前に、与えられたカスタムフィールド注入Beanインスタンスのコールバック春上で実行されます。このメソッドがfalseを返す場合、それは、ポストプロセッサInstantiationAwareBeanPostProcessor次のブロックが実行され、実行ロジックは、その後の充填性を防止します。
  
  postProcessPropertyValues
  
  それらが処理された後の工場は、豆の前に設定され、指定された属性値に適用されます。セッターの「必要な」Beanのプロパティの注釈に基づいて、例えば、すべての依存関係かどうかを調べることができます。また、通常、元のPropertyValuesに基づいてMutablePropertyValuesの新しいインスタンスを作成することで、交換用のプロパティ値を適用することができ、達成するために特定の値を追加または削除します。
  
  SmartInstantiationAwareBeanPostProcessor
  
  3つのメソッドを提供していますプロセッサ、スマートビーンのインスタンス化。
  
  predictBeanTypeの
  
  postProcessBeforeInstantiationコールバックハンドラからの予測には、Beanの最終型を返します。
  
  determineCandidateConstructorsは、
  
  ビーンをインスタンス化するコンストラクタを使用して決定しました。
  
  getEarlyBeanReference
  
  早期暴露Bean参照を取得し、早期のエクスポージャー豆だけで、完成はまだビーンのプロパティの割り当てと初期化を完了していないインスタンス化されます。
  
  MergedBeanDefinitionPostProcessor
  
  postProcessMergedBeanDefinition
  
  ビーン定義情報を合成後処理方法ビーンがインスタンス化した後、方法は、設定値の前に呼び出されます。
  
  自動化されたアセンブリは、達成するために
  
  必要な自動組立の要素を見つけます
  
  AutowiredAnnotationBeanPostProcessorポストプロセッサを加え@Autowiredと@value注釈要素の自動組立のために主に責任があります。だから、実際には、@Autowiredと@value注釈に解決、自動化されたアセンブリを必要とする要素を検索します。
  
  AutowiredAnnotationBeanPostProcessor自動実装要素の必要性を識別するために、ポストプロセッサは、この方法は、次のコールリンクMergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinitionで実現される:
  
  doWith:445、AutowiredAnnotationBeanPostProcessor $ 2(org.springframework.beans.factory.annotation)
  
  doWithLocalFields:657、 ReflectionUtils(org.springframework.util)
  
  buildAutowiringMetadata:433、AutowiredAnnotationBeanPostProcessor(org.springframework.beans.factory.annotation)
  
  findAutowiringMetadata:412、AutowiredAnnotationBeanPostProcessor(org.springframework.beans.factory.annotation)
  
  postProcessMergedBeanDefinition:235、AutowiredAnnotationBeanPostProcessor(org.springframework.beans.factory.annotation)
  
  applyMergedBeanDefinitionPostProcessors:1000、AbstractAutowireCapableBeanFactory(org.springframework.beans.factory.support)
  
  doCreateBean:523、AbstractAutowireCapableBeanFactory(org.springframework.beans.factory.support)
  
  したcreateBean: 483、AbstractAutowireCapableBeanFactory(org.springframework.beans.factory.support)
  
  のgetObject:312、AbstractBeanFactory $ -1(org.springframework.beans.factory.support)
  
  getSingleton:230、DefaultSingletonBeanRegistry(org.springframework.beans.factory.support)
  
  doGetBean:308 、AbstractBeanFactory(org.springframework.beans.factory.support)
  
  getBean:197、AbstractBeanFactory(org.springframework.beans.factory.support)
  
  の内部preInstantiateSingletons:761、DefaultListableBeanFactory(org.springframework.beans.factory.support)
  
  finishBeanFactoryInitialization:867、AbstractApplicationContext(org.springframework.context.support)
  
  リフレッシュ:543、 AbstractApplicationContext(xingtuylgw.com org.springframework.context.support)
  
  の<init>:84、AnnotationConfigApplicationContext(org.springframework.context.annotation)
  
  私たちは要素を見つける必要が自動組立工程findAutowiringMetadataに実装され、リンクから見ることができます、この方法は、メタデータ情報を構築するためにbuildAutowiringMetadataの道を呼び出すことになります。注釈は、それがオブジェクトAutowiredFieldElement内にカプセル化される特性にロードされている場合、アノテーションをメソッドに適用された場合、要素はAutowiredMethodElementオブジェクトにカプセル化されます。この方法は、本明細書で2つのオブジェクトがプロパティ値を注入確定する噴射、主な違いは、反射注射値を使用することは同じではありませんです。ソースは以下のとおりです。
  
  InjectionMetadata buildAutowiringMetadataプライベート(<?>最後のクラスclazz){
  
  のLinkedList <InjectionMetadata.InjectedElement>要素=新しい新しいのLinkedList <InjectionMetadata.InjectedElement>();
  
  クラスtargetClassのclazz = <?>;
  
  やる{
  
  //ストアメタデータ情報、我々は見つける
  
  決勝LinkedListの<InjectionMetadata.InjectedElement> = currElements
  
  新しい新規のLinkedList <InjectionMetadata.InjectedElement> www.haojiangyule.com();
  
  //すべてのクラスフィールドを反射することによってオブジェクトに対応する検索
  
  ReflectionUtils.doWithLocalFields(targetClass、新しい新しいReflectionUtils.FieldCallback(){
  
  @Overrideを
  
  ボイドdoWithパブリック(フィールド、フィールド)はIllegalArgumentException、IllegalAccessExceptionがスローを{
  
  //フィールドに反射して、すべてのアノテーション情報を検索し、そこ@Autowiredと@value注釈か否かを判断するには、フィールド内に封入されている場合AutowiredFieldElementオブジェクト
  
  アンfindAutowiredAnnotation = AnnotationAttributes(フィールド);
  
  (!= NULLアン)IF www.yuntianyul.com {
  
  IF(Modifier.isStatic(field.getModifiers())){
  
  IF(logger.isWarnEnabled(www.hongyaoyul.cn)){
  
  ロガー.WARN(「注釈Autowiredがサポートされていないが、静的フィールド上にある:」フィールド+);
 
  
  ブール= determineRequiredStatusが必要(アン);、
  
  // AutowiredFieldElementはキャッシュとにフィールドオブジェクトに封入
  
  currElements.add(新しいAutowiredFieldElement(フィールド、必須));
  
  }
  
  }
  
  });
  
  //メソッドは、反射によって、対応するすべてのクラスのオブジェクトを識別するために
  
  ReflectionUtils.doWithLocalMethods(targetClass、新しい新しいReflectionUtils.MethodCallback(){
  
  @Override
  
  公共ボイドdoWith(方法方法)はIllegalArgumentException、IllegalAccessExceptionがを{スロー
  
  BridgedMethod = BridgeMethodResolver.findBridgedMethod方法、(方法);
  
  (!BridgeMethodResolver.isVisibilityBridgeMethodPair(方法、bridgedMethod))IF {
  
  リターン;
  
  }
  
  //フィールド上の反射によってすべての注釈情報を検索し、@Autowiredと@value注釈が存在するか否かを判定する、オブジェクトAutowiredMethodElementのフィールドに存在封入されている場合
  
  AnnotationAttributes =アンfindAutowiredAnnotation(bridgedMethod);
  
  IF(!= NULL &&アンmethod.equals(ClassUtils.getMostSpecificMethod(方法、clazz))){
  
  IF(Modifier.isStatic(method.getModifiers( www.jintianxuesha.com))){
  
  IF(logger.isWarnEnabled()){
  
  logger.warn( "注釈Autowiredがサポートされていない静的メソッド上にある" +方法);
  
  }
  
  リターン;
  
  }
  
  (Method.getParameterTypes(www.baichuangyule IF .CN).LENGTH == 0){
  
  (logger.isWarnEnabled()){IF
  
  :logger.warn(+ "注釈万一AutowiredのみBEパラメータを用いて使用方法については"
  
  ;方法)
  
  }
  
  }
  
  ブール= determineRequiredStatusが必要(アン)
  
  のPropertyDescriptor PD = BeanUtils.findPropertyForMethod(bridgedMethod、clazz );
  
  //フィールドAutowiredMethodElementに密封オブジェクト
  
  currElements.add(新しい新しいAutowiredMethodElement(方法、必須、PD));
  
  }
  
  }
  
  });
  
  elements.addAll(www.yuchengyuledl.com 0、currElements);
  
  targetClass = targetClass.getSuperclass ();
  
  }
  
  //ループ処理が自動的に組み立てられる親要素
  
  一方(targetClass = NULL && targetClass = Object.classを!!);
  
  //自動的にInjectionMetadataオブジェクト定義をパッケージ化し、Beanにマージする必要がある要素を組み立てます
  
  新しい新しいInjectionMetadataリターン(clazz、エレメント);
  
  }
  
  自動組立工程が必要検索:
  
  反射して、クラスオブジェクトを、すべてのフィールド`Method````対象得る
  
  反射して、フィールド方式の取得および注釈を、そしてかどうかが判断@Autowiredと@value注釈
  
  注釈付き@Autowired @value及び方法フィールドおよびオブジェクトAutowiredMethodElement AutowiredFieldElementにカプセル化し、次の自動組立を待ちます。
  
  ループ処理は、自動組立の親要素を必要と
  
  自動的にパッケージInjectionMetadataオブジェクトに要素を組み立て、最後に定義された属性externallyManagedConfigMembers Beanにマージされ
  
  たプロパティ値注入
  
  AutowiredAnnotationBeanPostProcessorポストプロセッサ噴射特性値がpostProcessPropertyValuesプロセスで達成されます。:次のようにソース
  
  ます。public voidジェクト(オブジェクトのターゲット、文字列のbeanName、PropertyValuesのPVS)がThrowableを{スロー
  
  //自動アセンブリは、メタデータ情報を必要としなさい(それが取られているキャッシュ)を
  
  コレクション<InjectedElement> = elementsToIterate
  
  (!?this.checkedElements = nullのthis.checkedElements:this.injectedElements)。
  
  (!elementsToIterate.isEmpty())であれば{
  
  boolean型のデバッグ= logger.isDebugEnabled();
  
  用(InjectedElementエレメント:elementsToIterate){
  
  IF(デバッグ){
  
  logger.debug( '+のbeanName + "処理は、Beanの要素を注入" "':" +要素)
  
  }
  
  //调用AutowiredFieldElement或AutowiredMethodElement对象的注入方法注入属性值
  
  element.inject(ターゲットのbeanName、PVS)。
  
  }
  
  }
  
  }
  
  AutowiredFieldElement#注入
  
  @Overrideは
  
  空隙注入を保護された(オブジェクト・ビーン、文字列のbeanName、PropertyValuesのPVS)のThrowable {スロー
  
  フィールドフィールド=(フィールド)this.member。
  
  オブジェクトの値。
  
  IF(this.cached){
  
  値= resolvedCachedArgument(のbeanName、this.cachedFieldValue)。
  
  }
  
  他{
  
  DependencyDescriptorのDESC =新しいDependencyDescriptor(フィールド、this.required)。
  
  desc.setContainingClass(bean.getClass())。
  
  設定して<文字列> autowiredBeanNames =新しいLinkedHashSetの<文字列>(1);
  
  TypeConverterのTypeConverter = beanFactory.getTypeConverter()。
  
  試す{
  
  //在容器中获取需要装配的ビーン
  
  値= beanFactory.resolveDependency(DESC、のbeanName、autowiredBeanNames、にTypeConverter)。
  
  }
  
  ...
  
  }
  
  (!値= NULL){もし
  
  //通过反射设置属性值
  
  ReflectionUtils.makeAccessible(フィールド)。
  
  field.set(豆、値)。
  
  }
  
  }
  
  AutowiredMethodElement#注入
  
  @Overrideは
  
  空隙注入(オブジェクト・ビーン、文字列のbeanName、PropertyValuesのPVS)がThrowableを{スロー保護
  
  IF(checkPropertySkipping(PVS)){
  
  リターンします。
  
  }
  
  メソッドのメソッド=(方法)this.member。
  
  オブジェクト[]引数。
  
  もし(this.cached){
  
  //同期を回避するためのショートカット...
  
  引数=のresolveCachedArguments(のbeanName)。
  
  }
  
  他{
  
  <?>クラス[] paramTypes = method.getParameterTypes()。
  
  引数=新しいオブジェクト[paramTypes.length]。
  
  DependencyDescriptor []記述子=新しいDependencyDescriptor [paramTypes.length]。
  
  設定して<文字列> autowiredBeans =新しいLinkedHashSetの<文字列>(paramTypes.length)。
  
  TypeConverterのTypeConverter = beanFactory.getTypeConverter()。
  
  以下のために(INT i = 0; I <arguments.lengthを、iは++){
  
  MethodParameter methodParam =新しいMethodParameterを(方法I)。
  
  DependencyDescriptor currDesc =新しいDependencyDescriptor(methodParam、this.required)。
  
  currDesc.setContainingClass(bean.getClass())。
  
  記述子[I] = currDesc。
  
  試す{
  
  //在容器中获取需要装配的ビーン
  
  オブジェクトのarg = beanFactory.resolveDependency(currDesc、のbeanName、autowiredBeans、にTypeConverter)。
  
  場合(!argが== nullの&& this.required){
  
  引数= NULL;
  
  ブレーク;
  
  }
  
  引数[I] = argを、
  
  }
  
  キャッチ(BeansExceptionのEX){
  
  新しい新しいUnsatisfiedDependencyException投(ヌル、のbeanName、新しい新InjectionPoint(methodParam)、EX);
  
  }
  
  }
  
  ...
  
  }
  
  IF {(= nullを引数!)
  
  試し{
  
  反映メソッドを呼び出すことによって設定された//要素の値
  
  ReflectionUtils.makeAccessible(方法)を、
  
  方法.invoke(豆、引数);
  
  }
  
  ...
  
  }
  
  }
  
  ここから我々は、ソースとAutowiredMethodElement AutowiredFieldElement完全自動組立を見ることができビーンは、対応するコンテナを探しに行く、その後、取得した目標ビーンに設定することにより、反射され、豆の自動組立を完了するには、オブジェクト。
  
  要約
  
  我々は春豆を見ることができ、自動組立工程である:
  
  クラスオブジェクト、メソッドフィールドが反射して、すべての情報を取得する
  
  アノテーション情報を取得し、アノテーションの種類に応じての反射及び方法フィールドに、それが決定される自動組立がかどうかを
  
  自動的に組み立てることになりますオブジェクトAutowiredFieldElementとAutowiredMethodElementにカプセル化要素
  
  AutowiredFieldElementを呼び出して、次の工程を誘発する方法AutowiredMethodElementを注入
  
  容器を呼び出す()メソッドビーンソースデータがgetBeanによって注入する見つけるために
  
  ターゲットBeanに見出さビーンを反映し、ソースデータ
  
  の自動組立工程における問題も周期依存性を含みます、興味を持っているあなたは、この記事の春のソースを見ることができます(8)円形の依存関係

おすすめ

転載: www.cnblogs.com/dakunqq/p/11616446.html