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

}