如何在Spring中通过其bean名称自动装配接口的特定实现

时间:2018-03-24 19:19:08

标签: spring applicationcontext

我有实现MyInterface的类,例如: MyClassAMyClassB等。

如何通过它的bean名称获取类的实例?类似的东西:

context.getBean("myClassA")
context.getBean("myClassB")

如果不在XML中配置bean,我可以这样做吗? 我想使用注释

3 个答案:

答案 0 :(得分:1)

您可以使用qualifiers,例如:

@Component
@Qualifier("classA")
public MyInterface ClassA {
     return new ClassA();
}

@Component
@Qualifier("classB")
public MyInterface ClassB {
     return new ClassB();
}

并使用它:

public class SomeClass {
    @Autowired
    @Qualifier("classA")
    private MyInterface classA;
}

答案 1 :(得分:0)

这里有几个选项。最简单的方法是使用@Autowire

将字段名称用作组件名称
@Component("testClassA") // It is possible to omit explicit bean name declaration here since Spring will use a class name starting from lower case letter as a bean name by default. So just `@Component` should be sufficient here and below.
public TestClassA implements MyInterface {

}

@Component("testClassB")
public TestClassB implements MyInterface {

}

/*
 * Note that field names are the same as the component names.
 */
@Component
public class TestClassWithDependencies {
    @Autowired
    private MyInterface testClassA;

    @Autowired
    private MyInterface testClassB;
}

另一种选择是使用qualifiers

@Component
@Qualifier("testClassA")
public TestClassA implements MyInterface {

}

@Component
@Qualifier("testClassB")
public TestClassB implements MyInterface {

}

@Component
public class TestClassWithDependencies {
    @Autowired
    @Qualifier("testClassA")
    private MyInterface testClassA;

    @Autowired
    @Qualifier("testClassB")
    private MyInterface testClassB;
}

当您需要反复使用相同的限定符时,您甚至可以创建自己的元注释:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("testClassA")
public @interface TestClassACustomQualifier {
    String value();
}

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier("testClassB")
public @interface TestClassBCustomQualifier {
    String value();
}

@Component
public class TestClassWithDependencies {
    @Autowired
    @TestClassACustomQualifier
    private MyInterface testClassA;

    @Autowired
    @TestClassBCustomQualifier
    private MyInterface testClassB;
}

更漂亮,不是吗?还有一个选择是使用JSR-250规范中的 @Resource 。正如@hovanessyan所指出的那样,JavaEE的做事风格更多,但我认为这是一种在许多项目中使用的可行方法:

@Component("testClassA")
public TestClassA implements MyInterface {

}

@Component("testClassB")
public TestClassB implements MyInterface {

}
@Component
public class TestClassWithDependencies {
    @Resource(name="testClassA")
    private MyInterface testClassA;

    @Resource(name="testClassB")
    private MyInterface testClassB;
}

您可以了解更多信息https://www.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/,其中讨论了添加测试的不同方法。

希望这有帮助!

答案 2 :(得分:0)

我认为如果以上选项不够,那么factory implementation是获取实例的一种方法 -

@Component
public TestClassA implements MyInterface {

}

@Component
public TestClassB implements MyInterface {

}

以这种方式定义工厂 -

public class MyInterfaceFactory extends AbstractFactoryBean<MyInterface> {

    private String filter;
    @Override
    public Class<?> getObjectType() {
        return MyInterface.class;
    }

    @Override
    protected MyInterface createInstance() throws Exception {
        MyInterface myInterface;
        switch (filter)
        {
            case "1":
                myInterface = new TestClassA();
                break;
            case "2":
                myInterface = new TestClassB();
                break;
            default: throw new IllegalArgumentException("No such type.");
        }

        return myInterface;
    }
}

and then your bean config -

@Configuration
public class FactoryBeanConfig {

    @Bean(name = "myInterface")
    public MyInterfaceFactory myInterfaceFactory() {
        MyInterfaceFactory factory = new MyInterfaceFactory();
        factory.setFilter("7070");
        return factory;
    }
}