Spring Bean实现多个接口

时间:2015-07-20 11:05:31

标签: java spring dependency-injection inject

我有一个实现两个接口的bean。准系统代码如下:

interface InterfaceA {
  ...
}

interface InterfaceB {
  ...
}

public class ClassC implements InterfaceA, InterfaceB {
  ...
}

在我的AppConfig中,我指定了以下内容:

@Bean(name = "InterfaceA")
public InterfaceA interfaceA() {
    return new ClassC();
}

@Bean(name = "InterfaceB")
public InterfaceB interfaceB() {
    return new ClassC();
}

我这样使用它:

public class MyClass {

    @Inject
    private final InterfaceA a;

    public MyClass(@Named("InterfaceA") InterfaceA a) {
        this.a = a;
    }
     ...
}

然而,Spring抱怨说:

  

没有类型的限定bean   [com.example.InterfaceA]是   已定义:预期单个匹配bean但找到2:   InterfaceA,InterfaceB

类似的问题被问到并回答了EJB here,但我找不到任何针对Spring bean的东西。有人知道原因吗?

解决方法是引入一个新接口,扩展InterfaceAInterfaceB,然后让ClassC实现。但是,由于框架限制,我不愿改变我的设计。

2 个答案:

答案 0 :(得分:1)

感谢您提出的好问题。

就我而言,我创建了一个扩展 A 和 B 的接口:

SELECT am.* FROM bettha_adherence_area_manager am
               INNER JOIN bettha_adherence_area aa ON am.bettha_adherence_area_id = aa.id
               INNER JOIN selection_process sp ON aa.selection_process_id = sp.selection_process_id
               INNER JOIN company_country cc ON sp.company_country_id = cc.company_country_id
               INNER JOIN bettha_adherence_area_manager_execution baame on am.bettha_adherence_area_manager_id = baame.bettha_adherence_area_manager_id
            WHERE cc.company_country_id = :companyCountryId AND
               (LOWER(am.email) LIKE LOWER(CONCAT('%', :search, '%')) OR
               LOWER(am.full_name) LIKE LOWER(CONCAT('%', :search, '%'))) AND
               CASE WHEN (:isFinished IS NOT NULL) THEN (
                   CASE WHEN (baame.finished_date IS NOT NULL) THEN
                       (:isFinished)
                   ELSE
                       NOT :isFinished END
               )
               ELSE TRUE END
            GROUP BY am.email;

...以及通用实现实现统一接口:

public interface InterfaceC extends InterfaceA, InterfaceB {}

这个统一的接口允许创建单个 bean:

public class ClassC implements InterfaceC {
  //...
}

然后,Spring 框架能够将通用实现注入或自动装配到以主要接口表示的依赖项:

@Bean
public InterfaceC implementationForAandB() {
    return new ClassC();
}

}

答案 1 :(得分:0)

春天是对的...当你写作

@Bean(name = "InterfaceA")
public InterfaceA interfaceA() {
    return new ClassC();
}

@Bean(name = "InterfaceB")
public InterfaceB interfaceB() {
    return new ClassC();
}

Spring创建ClassC个对象,一个名为InterfaceA,另一个InterfaceB,两者都实现了InterfaceA和InterfaceB。

然后当你写:

@Inject
private final InterfaceA a;

你要求Spring找到一个bean 实现 InterfaceA,但如上所述有2个错误。

您可以只创建一个ClassC类型的对象,也可以使用@Qualifier@Named注释:

@Inject
@Named("InterfaceA")
private final InterfaceA a;

这样,你明确地要求Spring找到名为 InterfaceA的bean ,并且希望它现在是唯一的。