1

我正在使用 Spring 3.2.2 并且想知道是否有一种方法可以按类类型注入 bean 而无需显式地给它们一个字符串名称。前任:

@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] 类型的合格 bean:预期单个匹配 bean,但找到 2:myClass,myOtherClass

有没有办法说“使用与类名完全匹配的”而不使用字符串名称?

换句话说,我不想这样做:

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

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

谢谢!

4

3 回答 3

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但这在使用or时不起作用@Autowire

要在自动装配时强制进行严格的类匹配,您可以用 a替换默认值AutowireCandidateResolver,但这似乎不是一个好主意,因为或者可以解决 NUBDE 问题。BeanFactoryBeanFactoryPostprocessor@Resource@Qualify

例如:(未测试)

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

}
于 2013-03-20T17:28:19.310 回答
1

每当您遇到非唯一依赖 bean 定义时,这就是Spring 手册第 5.4.5 节的建议:

  • 放弃自动装配以支持显式装配。
  • 通过将其 autowire-candidate 属性设置为 false 来避免自动装配 bean 定义,如下一节所述。
  • 通过将其元素的主要属性设置为 true,将单个 bean 定义指定为主要候选者。
  • 如果您使用的是 Java 5 或更高版本,请使用基于注解的配置实现更细粒度的控制,如第 5.9 节“基于注解的容器配置”中所述。
于 2013-03-20T13:34:27.223 回答
0

尝试在您的类上使用@Component(服务、存储库、控制器),并在注入 bean 时使用 @Autowired。

编辑:我的错,我没有很好地阅读这个问题。问题是您实际上有 2 个 MyClass 实例(因为 MyOtherClass 从 MyClass 扩展)。因此,除了给类名之外别无他法,否则您将始终以 NoUniqueBeanDefinitionExceptions 告终。

于 2013-03-20T13:01:58.887 回答