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

意味着,如果沒有多於1個具有所需類型的bean,則所有bean的字段將自動注入依賴關係。@Autowired和default-autowire可以共存嗎?

現在的問題是如何使用註釋時工作,它是否工作。

我的測試結果顯示,即使我用

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

的情況下試圖通過自動裝配類型的字段,如果有是Foo多個實現失敗。所以,對於我所看到的,default-autowire不會與註釋混合使用。我無法在文檔中找到任何具體內容。

爲了擴展這個問題 - 當xml-only被使用時,彈簧如何與默認自動裝配一起工作。即如果你有<property>。屬性注入是否覆蓋默認值(應該是)。

我可以做更多的測試,但我更喜歡行爲被一些報價確認。任何見解?

+0

特別沒有用注:在類似的情況下,我看源代碼;它比寫和發佈答案花費的時間更少,並且使我確信我確切地知道爲什麼/如何。不幸的是,我不使用春天,所以沒有直接的答案。 – bestsss

+2

@bestsss我也是這麼做的。即使我對Spring的代碼非常熟悉(在各種場合做過這些),自動裝配機制也有點困難。如果我遇到這個問題,也許我會花一些時間研究。目前它出於好奇,所以我只是在檢查是否有人已經意識到這一點。 – Bozho

+0

*有點難*;我的猜測(沒有任何經驗)在一個setter的斷點,你確定你不會自己調用,檢查堆棧跟蹤。直到代碼(或缺少)綁定指定的資源。並讚揚你自己做。我幾乎完全從源代碼編譯第三方庫(開源)。 – bestsss

回答

1

編輯:

請問物業注入覆蓋默認的(應該是)。

你說得對。如果您不希望Spring向bean的某個字段注入依賴項,則可以使用@Qualifier註釋來注入所需的依賴項。我仍然在試圖找到可以證實它—我能找到的最接近的文件是在春天論壇上一個帖子override default-autowire setting with an annotation?

編輯:這是另一篇文章@Resource considered only after default-autowire="byName"描述使用新InstantiationAwareBeanPostProcessor改變接線纔能有@ setter上的資源優先於default-autowire。

0

據我所知,default-autowire屬性爲那些只在XML配置中綁定的bean定義了默認的「自動裝配模式」!然後基於註釋的自動裝配與此無關。 @Autowired總是按類型,@Resource總是的名稱!
請參閱Spring的參考文檔3.9.3中的提示:
「如果您打算按名稱表示註解驅動的注入,則不要主要使用@Autowired,即使在技術上能夠通過@Qualifier引用bean名稱值,而是使用JSR-250 @Resource註釋,它的語義定義是通過其唯一名稱來標識特定的目標組件,而聲明的類型與匹配過程無關。「

+1

是的,但如果你同時使用它,它不起作用。這並不是說我期望default-autowire可以用於註釋工作,但它會忽略註釋並且失敗。 – Bozho

+0

你的意思是你使用'@Resource(name =「someConcreteFoo」)private Foo foo;''用'default-autowire =「byType」'和'default-autowire =「byName」'接收到一個異常, ?這將是我假設的Spring中的一個錯誤。 – Robin

+0

與任何默認自動裝配,而不僅僅是byType。重點是 - 如果你想使用註釋,你不能擁有默認自動裝配。我想確保是這種情況 – Bozho

3

我在調試這個問題時遇到了一個問題,我認爲這可能是春季的一個bug。在我看來,這個問題從下面的代碼中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); 
} 

源於我個人認爲應用自動裝配的順序和InstantiationAwareBeanPostProcessor是錯誤的,因爲@Resource註解只會在postProcessPropertyValues應用,所以後自動裝配(自動裝配已經失敗了)。

現在我不知道在改變調用順序時是否會產生影響,以便在自動裝配之前解決@Resource註釋,但這可能是一個提升爲bug /修復的東西(我使用過加載我的測試應用程序上下文來解決這個問題)的方式如下:

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); 
       } 
      }; 
     } 
    }; 

希望幫助

相關問題