2013-03-20 41 views
1

我使用Spring 3.2.2並想知道是否有一種方法可以通過類類型注入bean,而不必明確地給它們一個字符串名稱。例:命名類的NoUniqueBeanDefinitionException

@Named 
public MyClass{ 
} 

@Named 
public MyOtherClass extends MyClass{ 
} 

@Named 
public class Foo{ 
    public void blah(){ 
     MyClass myClass = context.getBean(MyClass.class); 
    } 
} 

這將產生:

org.springframework.beans.factory.NoUniqueBeanDefinitionException:式[MyClass的]被定義的任何合格的豆:預期單一匹配豆但發現2:MyClass的,myOtherClass

有沒有一種方法可以說「使用與類名完全匹配的名稱」而不使用字符串名?

換句話說,我不想做的事:

@Named("MyClass")... 
@Named("MyOtherClass")... 

MyClass myClass = context.getBean("MyClass"); 

謝謝!

回答

0

請在您的類上使用@Component(Service,Repository,Controller),並在注入bean時使用@Autowired。

編輯:我的壞,我沒有太好的問題。問題是你實際上有2個MyClass實例(因爲MyOtherClass從MyClass擴展)。因此除了給出類名以外別無他法,否則最終會導致NoUniqueBeanDefinitionException異常。

+0

有沒有辦法用@Named做到這一點?我寧願使用JSR標準 – user973479 2013-03-20 13:07:35

+0

你說你已經在使用Spring 3.2.2,那爲什麼你不使用它的註釋? – 2013-03-20 13:18:12

+0

我更喜歡JSR註釋,所以更容易切換道路(如有必要)。從Spring使用JSR註釋沒有任何問題。除非Spring註釋專門提供了一個工作解決方案,否則我沒有看到切換的有效理由 – user973479 2013-03-20 13:19:57

1

這是當你遇到非唯一依賴bean定義什麼§ 5.4.5 of Spring manual建議:

  • 放棄自動裝配有利於明確的佈線。
  • 通過將autowire-candidate屬性設置爲false,避免爲bean定義進行自動裝配,如下一節所述。
  • 通過將其元素的主屬性設置爲true來指定單個bean定義作爲主要候選者。
  • 如果你正在使用Java 5或更高版本,實現更細粒度的控制可以使用基於註解的配置,如Section 5.9, 「Annotation-based container configuration」.
1

對於爲例進行說明,你可以這樣做:

@Named 
public class Foo{ 
    public void blah(){ 
     MyClass myClass = getBean(MyClass.class); 
    } 

    private <T> T getBean(Class<T> type) { 
     return context.getBean(Introspector.decapitalize(type.getSimpleName()), type); 
    } 
} 

但是,當使用@Inject@Autowire時,這不起作用。

強制限制類匹配自動裝配的時候,你可以替換默認AutowireCandidateResolverBeanFactoryBeanFactoryPostprocessor,但似乎不是一個好主意,因爲@Resource@Qualify可以解決NUBDE問題。

例如:(未測試)

public class StrictClassAutowireCandidateResolver implements AutowireCandidateResolver { 

    @Override 
    public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { 
     if (!bdHolder.getBeanDefinition().isAutowireCandidate()) { 
      return false; 
     } 

     if (descriptor == null) { 
      return true; 
     } 

     String className = null; 

     if (descriptor.getField() != null) { 
      className = descriptor.getField().getType().getName(); 
     } 

     else if (descriptor.getMethodParameter() != null) { 
      className = descriptor.getMethodParameter().getParameterType().getName(); 
     } 

     Class<?> clazz = null; 
     try { 
      clazz = Class.forName(className); 
     } 
     catch (Exception e) { 
      return false; 
     } 

     if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { 
       // have no chances to be strict, let BeanFactory to find implementations. 
       return true; 
      } 

     return bdHolder.getBeanDefinition().getBeanClassName().equals(className); 
    } 

    @Override 
    public Object getSuggestedValue(DependencyDescriptor descriptor) { 
     return null; 
    } 

}