Spring 4 - Autowire 通用接口

Clé*_*ent 5 java generics spring autowired

从 Spring (v4.3.8) 开始,当 Spring 尝试加载依赖注入时遇到问题。

我想根据 T 的类型(Debit1 或 Debit2)调用 ManagerImpl1.java 或 ManagerImpl2.java 实现的“管理”方法。详细信息如下:

引起:org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有类型为“com.xxx.xxx.datacollection.infoprod.Manager”的合格bean可用:预期单个匹配bean但找到2:ManagerImpl1,ManagerImpl2

业务.java:

@Component
public class Business<T extends Debit> {

    @Autowired
    private Manager<T> manager;

    public void treatment(Context<T> context, FindServiceReturnMessage response) {

        manager.manage(response, context);
    }
Run Code Online (Sandbox Code Playgroud)

管理器.java:

public interface Manager<T extends Debit> {

    void manage(final FindServiceReturnMessage response, Context<T> context);
}
Run Code Online (Sandbox Code Playgroud)

ManagerImpl1.java:

@Component
public class ManagerImpl1 implements Manager<Debit1> {

    @Override
    public void manage(final FindServiceReturnMessage response, Context<Debit1> context) {

    }
}
Run Code Online (Sandbox Code Playgroud)

ManagerImpl2.java:

@Component
public class ManagerImpl2 implements Manager<Debit2> {

    @Override
    public void manage(final FindServiceReturnMessage response, Context<Debit2> context) {

    }
}
Run Code Online (Sandbox Code Playgroud)

此外,“Debit1”和“Debit2”实现接口“Debit”。

我尝试了几件事但没有成功......

Dam*_*mCx 1

您需要在 Bean 上添加一个限定符,如下所示:

@Component
@Qualifier("managerImpl2")
public class ManagerImpl2 implements Manager<Debit2> {

    @Override
    public void manage(final FindServiceReturnMessage response, Context<Debit2> context) 
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当您想使用它时,再次使用您的@Qualifier注释:

@Component
public class Business<T extends Debit> {

    @Autowired
    @Qualifier("managerImpl2")
    private Manager<T> manager;

    public void treatment(Context<T> context, FindServiceReturnMessage response) {

        manager.manage(response, context);
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,正如 @dvorog 在评论中所说,由于编译时不存在泛型,您可能必须创建一个如下所示的业务接口:

public interface Business<T extends Debit> {

    public void treatment(Context<T> context, FindServiceReturnMessage response);
}
Run Code Online (Sandbox Code Playgroud)

并实现 BusinessImpl 以在每次有新类型时指定它Debit

@Component
public class ManagerImpl2Business<Debit2> {

    @Autowired
    @Qualifier("managerImpl2")
    private Manager<Debit2> manager;

    public void treatment(Context<Debit2> context, FindServiceReturnMessage response) {

        manager.manage(response, context);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将重复一个步骤,并且可能会以一些无法维护的代码结束,或者if (T instanceof Debit1)在某些地方使您的通用性发挥作用。