2011-02-28 11 views
6
<beans default-autowire="byType /> 

は、必要な型のBeanが2つ以上ない場合、すべてのBeanのフィールドに自動的に依存関係が挿入されることを意味します。@Autowiredとdefault-autowireは共存できますか?

注釈が使用されているときにこれがどのように機能し、まったく機能するのでしょうか。

私のテストは、私は

@Resource(name="someConcreteFoo") 
private Foo foo; 

を使用している場合でも、コンテキストは種類によってフィールドをautowireしようとFooの複数の実装がある場合、失敗したことを示しました。ですから、私が見るところでは、default-autowireは注釈と混ざりません。私はドキュメンテーションで特定のものを見つけることができませんでした。

質問を拡張する - xml-onlyが使用されているとき、springはどのようにdefault-autowiringで動作しますか?私。 <property>がある場合。プロパティインジェクションは、デフォルト(それはそうであるべきです)をオーバーライドしますか?

私はより多くのテストを行うことができますが、いくつかの見積もりでその動作を確認したいと思います。どんな洞察?

+0

特にない便利なノートを支援します。私は、ソースコードを見て似たようなケースでは、それは答えを書いて投稿するよりも時間がかからず、私が正確に理由/方法を知っていることを確認します。残念ながら、私は春を使用しないので、まっすぐ答えはありません。 – bestsss

+2

@bestsss私もそうします。そして、私は春のコードにかなり精通していますが(これをさまざまな場面で行っています)、オートワイヤリングの仕組みは少し難しくなります。もし私がこれに問題を抱えていたなら、多分私は研究に数時間を費やしていたでしょう。現在、それは不思議の国のアリスだから、誰かがすでにこれを認識しているかどうかを確認しているだけです。 – Bozho

+0

*少し難しい*;私の推測(任意の経験なし)のセッターで、あなたは自分で電話をしないと確信して、スタックトレースを調べてください。指定されたリソースをコード化する(または不足する)までステップを進めます。そして、あなた自身でそれをやっていることについての賞賛。私はほとんどの場合、第三者のライブラリ(オープンソースのもの)をソースからコンパイルします。 – bestsss

答えて

1

編集:

プロパティ注射は(それがあるべき)デフォルトを上書きありません。

あなたは正しいです。 SpringにBeanの特定のフィールドへの依存性を注入させたくない場合は、@Qualifierアノテーションを使用して依存関係を注入することができます。ここで持っている配線順序を変更するには、新しいInstantiationAwareBeanPostProcessorを使用して説明し、他のポスト@Resource considered only after default-autowire="byName"がある:私はまだ春のフォーラムにoverride default-autowire setting with an annotation?

編集ポストされて、それは私が見つけることができる最も近い—確認します文書を見つけようとしていますsetterの@Resourceはdefault-autowireよりも優先されます。

0

私が知っている限り、default-autowire属性は、あなたのXML構成でのみ配線されているbeanのデフォルトの "autowire mode"を定義しています!その後、注釈ベースの自動配線はそれとは独立しています。 @Autowiredは、は、常にとなります。
Springのリファレンスドキュメントのヒント3.9.3を参照してください:
"アノテーション駆動型の注入を名前で表現する場合は、技術的に@QualifierによってBean名を参照できる場合でも、@Autowiredを主に使用しないでください特定のターゲットコンポーネントを固有の名前で識別するために意味的に定義されているJSR-250 @Resourceアノテーションを使用します。宣言されたタイプは、マッチングプロセスとは関係ありません。

+1

はい、両方を使用すると動作しません。注釈を処理するためにデフォルトのオートワイヤーが期待されるわけではありませんが、注釈は無視されて失敗します。 – Bozho

+0

'defaultResource(name =" someConcreteFoo ")private Foo foo;'と 'default-autowire =" byType "と' default-autowire = "byName"を使って例外が発生したということです。例外は発生しません?これは私が前提とするSpringのバグでしょう。 – Robin

+0

には、byTypeだけでなく、デフォルトのautowireがあります。要点は、注釈を使用する場合はデフォルトの自動配線を使用できません。私はこれが本当であることを確認したかった – Bozho

3

私はこの問題をデバッグするのに速い刺し傷があり、これは春のバグかもしれません。私の意見では、問題は、私は後のように、@Resourceアノテーションは唯一、postProcessPropertyValuesに適用されるようにオートワイヤリングとInstantiationAwareBeanPostProcessorを適用する順序は、間違っていると思うAbstractAutowireCapableBeanFactory個人的に

/** 
* Populate the bean instance in the given BeanWrapper with the property values 
* from the bean definition. 
* @param beanName the name of the bean 
* @param mbd the bean definition for the bean 
* @param bw BeanWrapper with bean instance 
*/ 
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { 
    PropertyValues pvs = mbd.getPropertyValues(); 

    if (bw == null) { 
     if (!pvs.isEmpty()) { 
      throw new BeanCreationException(
        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); 
     } 
     else { 
      // Skip property population phase for null instance. 
      return; 
     } 
    } 

    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the 
    // state of the bean before properties are set. This can be used, for example, 
    // to support styles of field injection. 
    boolean continueWithPropertyPopulation = true; 

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 
     for (BeanPostProcessor bp : getBeanPostProcessors()) { 
      if (bp instanceof InstantiationAwareBeanPostProcessor) { 
       InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 
       if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { 
        continueWithPropertyPopulation = false; 
        break; 
       } 
      } 
     } 
    } 

    if (!continueWithPropertyPopulation) { 
     return; 
    } 

    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || 
      mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 
     MutablePropertyValues newPvs = new MutablePropertyValues(pvs); 

     // Add property values based on autowire by name if applicable. 
     if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { 
      autowireByName(beanName, mbd, bw, newPvs); 
     } 

     // Add property values based on autowire by type if applicable. 
     if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 
      autowireByType(beanName, mbd, bw, newPvs); 
     } 

     pvs = newPvs; 
    } 

    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); 

    if (hasInstAwareBpps || needsDepCheck) { 
     PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); 
     if (hasInstAwareBpps) { 
      for (BeanPostProcessor bp : getBeanPostProcessors()) { 
       if (bp instanceof InstantiationAwareBeanPostProcessor) { 
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 
        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 
        if (pvs == null) { 
         return; 
        } 
       } 
      } 
     } 
     if (needsDepCheck) { 
      checkDependencies(beanName, mbd, filteredPds, pvs); 
     } 
    } 

    applyPropertyValues(beanName, mbd, bw, pvs); 
} 

に次のコードから茎autowiring(autowiringが既に失敗した時間)。

呼び出しの順番を変えることに影響があるかどうかわからないので、@Resource注釈は自動配線する前に解決されますが、これはバグ/修正となる可能性があります)この問題を解決するために私のテストアプリケーションコンテキストをロードする次の方法:

ApplicationContext ctx = new ClassPathXmlApplicationContext("test/appctx.xml") { 
     protected org.springframework.beans.factory.support.DefaultListableBeanFactory createBeanFactory() { 
      return new DefaultListableBeanFactory(getInternalParentBeanFactory()) { 
       protected void populateBean(String beanName, org.springframework.beans.factory.support.AbstractBeanDefinition mbd, org.springframework.beans.BeanWrapper bw) { 
        PropertyValues pvs = mbd.getPropertyValues(); 

        if (bw == null) { 
         if (!pvs.isEmpty()) { 
          throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); 
         } 
         else { 
          // Skip property population phase for null instance. 
          return; 
         } 
        } 

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the 
        // state of the bean before properties are set. This can be used, for example, 
        // to support styles of field injection. 
        boolean continueWithPropertyPopulation = true; 

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { 
         for (BeanPostProcessor bp : getBeanPostProcessors()) { 
          if (bp instanceof InstantiationAwareBeanPostProcessor) { 
           InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 
           if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { 
            continueWithPropertyPopulation = false; 
            break; 
           } 
          } 
         } 
        } 

        if (!continueWithPropertyPopulation) { 
         return; 
        } 

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); 
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); 

        if (hasInstAwareBpps || needsDepCheck) { 
         PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); 
         if (hasInstAwareBpps) { 
          for (BeanPostProcessor bp : getBeanPostProcessors()) { 
           if (bp instanceof InstantiationAwareBeanPostProcessor) { 
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; 
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 
            if (pvs == null) { 
             return; 
            } 
           } 
          } 
         } 
         if (needsDepCheck) { 
          checkDependencies(beanName, mbd, filteredPds, pvs); 
         } 
        } 

        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || 
          mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 
         MutablePropertyValues newPvs = new MutablePropertyValues(pvs); 

         // Add property values based on autowire by name if applicable. 
         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { 
          autowireByName(beanName, mbd, bw, newPvs); 
         } 

         // Add property values based on autowire by type if applicable. 
         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { 
          autowireByType(beanName, mbd, bw, newPvs); 
         } 

         pvs = newPvs; 
        } 

        applyPropertyValues(beanName, mbd, bw, pvs); 
       } 
      }; 
     } 
    }; 

希望

関連する問題