Spring Java Config - 使用接口(interface)公开 bean

标签 spring dependency-injection spring-java-config

我有一个类,假设“DefaultService”实现了两个接口(interface):“Service1”和“Service2”。 Spring java 配置如下所示:

@Bean
Service1 defaultService() {
    return new DefaultService();
}

现在,我有另一个需要“Service2”的 bean Foo。

public class Foo implements AnotherInterface {
   @Autowired
   private Service2 service2;
}

这个bean也是通过Java配置来配置的:

@Bean
AnotherInterface anotherInterface(){
   return new Foo();
}

Spring 不喜欢这种配置。我认为这是有道理的,因为“DefaultService”被公开为“Service1”,而不是“Service2”(Foo 需要)。

No qualifying bean of type [...Service2] found for dependency: expected at least 1 bean which qualifies ...

当然,我可以将 DefaultService 公开为 Service2。但是如果有另一个 bean 需要 Service1 该怎么办?对于这种情况,Spring 有什么建议?我发现的另一个(奇怪的)问题是以下配置有效:

@Bean
Service2 defaultService(){ // exposing the bean as Service2, to fix dependency on Foo
   return new DefaultService(); 
}

@Bean
AnotherDependant anotherDependant(Service1 service1){
   return new AnotherDependant(service1);
}
Spring 如何将 Service1 连接到“AnotherDependant”的配置声明(它对我在第一个场景中使用的 @Autowired 不满意)? 我正在使用 Spring 3.2.2.RELEASE,尽管我怀疑版本是否真的很重要..

我最好的解决方法是:

@Bean
DefaultService defaultService(){
return new DefaultService();
}

@Bean
Service1 service1(){
return defaultService();
}

@Bean
Service2 service2(){
return defaultService();
}

但是这太丑了......

================================================== ======================= 回复@Oskar。 基本上,@Oskar 的建议与在 xml 中声明两个相同。即在 spring 容器中创建同一类的两个实例。

public interface Driveable {}
public interface Vehicle {}
public class Car implements Vehicle, Driveable{}


@Configuration
public class Config {
    @Bean
    public Vehicle vehicle() {
        return new Car();
    }
    @Bean
    public Driveable driveable() {
        return new Car();
    }
}

public class Main {
    public static void main(String[] args) {
        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

        final Driveable driveable = context.getBean("driveable", Driveable.class);
        final Vehicle vehicle = context.getBean("vehicle", Vehicle.class);
        System.out.println(driveable == vehicle);
    }
}

最佳答案

public interface Driveable {}
public interface Vehicle {}

@Component
public class Car implements Vehicle, Driveable{}


@Configuration
public class Config {

    @Autowired
    private Car car;

    @Bean
    public Vehicle vehicle() {
        return car;
    }

    @Bean
    public Driveable driveable() {
        return car;
    }
}

public class Application {

    public static void main(String[] args) throws Exception {
        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class, Car.class);
        final Driveable driveable = context.getBean("driveable", Driveable.class);
        final Vehicle vehicle = context.getBean("vehicle", Vehicle.class);
        System.out.println(driveable == vehicle);
    }

}

以问题中的汽车为例,

  1. 将 Car 定义为 @Component。
  2. 在 Config 中声明一个 Autowiring 的字段 Car car
  3. 使用从 @Bean 注解方法返回的 Autowiring 字段。

如果我们使用@ComponentScan,汽车组件将被自动选取。另外,如果我们自己创建上下文,我们可以在 AnnotationConfigApplicationContext 构造函数中传递 Car 类(如代码所示)。

关于Spring Java Config - 使用接口(interface)公开 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33904597/

相关文章:

java - 如何使用 ServletContextPropertyPlaceholderConfigurer 中从数据库加载的属性覆盖从文件加载的属性?

java - 当前不支持公式映射 - Hibernate ORM Envers

swift - 如何避免我的自定义依赖项注入(inject)工具出现保留周期?

php - 单例和服务定位器的真正替代品?

java - 无论我使用哪个 JEE 异常(exception),Postman 都会返回状态 500

java - 如何在 Spring 中提供 Autowiring 的基类?

java - 动态注入(inject)属性到spring

java - Spring AbstractAnnotationConfigDispatcherServletInitializer 未找到 WebApplicationContext : no ContextLoaderListener registered

java - Spring Java 配置和 BeanFactoryPostProcessor

用于 jasypt 和配置文件的 Spring 4 javaconfig