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ただし、またはを使用する場合、これは機能しません@Autowire

自動配線時に厳密なクラス マッチングを強制するには、 のデフォルトを に置き換えることができますが、AutowireCandidateResolverNUBDE問題を解決できる、または解決できるため、良い考えとは思えません。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

これは、Spring マニュアルの§ 5.4.5 が、一意でない依存関係 Bean 定義に遭遇するたびに提案するものです。

于 2013-03-20T13:34:27.223 に答える
0

クラスで @Component (Service、Repository、Controller) を使用し、Bean を注入するときは @Autowired を使用してみてください。

編集:私の悪い、私は質問をよく読んでいませんでした。問題は、実際には MyClass のインスタンスが 2 つあることです (MyOtherClass は MyClass から拡張されているため)。したがって、クラス名を指定する以外に方法はありません。そうしないと、常に NoUniqueBeanDefinitionExceptions が発生します。

于 2013-03-20T13:01:58.887 に答える