Spring自动装配参数化泛型类型

时间:2014-04-04 07:40:59

标签: java spring generics spring-4

Spring 4包含对泛型类型解析的主要增强,但是当在包含bean类上参数化类型参数时,我在自动装配泛型类型方面遇到了麻烦。

我需要跟踪提交到外部服务的作业的状态,我想在每个作业启动时创建一个条目,并在收到回发时清除或更新它。我通常会尝试将持久性策略与服务接口分开,因此我有一个接口JobStatus和一个Spring Data Mongo类MongoJobStatus implements JobStatus。由于作业可能在外部服务有机会为其分配ID(例如,HTTP 502)之前失败,因此我需要将JobStatus传递回服务以识别更新:

interface JobStatusService<S extends JobStatus> {
    S beginJob(...);
    S updateJobStatus(S targetJob, Status newStatus);
    void finishJob(S targetJob);
}

因此,我的Spring控制器可以处理作业并记录回发,就像这样;控制器类带有一个类型参数,以便我可以存储新的状态对象并将其传递回服务:

@Controller
public class JobController<JS extends JobStatus> {
    @Autowired JobStatusService<JS> jobService;

    ... handler method ...
    JS status = jobService.createJob(info, goes, here);
    // submit job via HTTP
    jobService.updateJobStatus(status, Status.PROCESSING);
    ...
}

我的MongoDB支持的实现如下所示:

public class MongoJobStatusService implements JobStatusService<MongoJobStatus> {
    MongoJobStatus beginJob(...) {...}
    MongoJobStatus updateJobStatus(MongoJobStatus job, Status newStatus) {...}
}

当我尝试启动时,Spring上下文失败,NoSuchBeanDefinitionExceptionJobStatusService。我已经确认,如果我设置required=falseMongoJobStatusService bean正确地进行组件扫描并安装在上下文中,但Spring似乎无法理解该类实现了参数化通用接口。

有没有办法向Spring指定我需要一个bean实现一个泛型接口,该接口的类型参数在包含bean级别进行参数化,而不是作为字段级别的文字类型参数嵌入?

3 个答案:

答案 0 :(得分:2)

尝试添加:

 @Autowired 
 @Qualifier("mongoJobStatusService")
 JobStatusService<JS> jobService;

并指定MongoJobStatusService bean的名称。

答案 1 :(得分:1)

Spring容器似乎无法解决控制器类上可接受的类型参数,但如果显式提供了这些类型参数,它可以解决注入的字段。通过使用文字类型对控制器类进行子类化,我能够通过次优解决问题:

@Controller
public class MongoJobController<MongoJobStatus> {}

我已为此opened a JIRA issue并拥有a minimal example on GitHub

答案 2 :(得分:1)

事实上Spring并没有找到匹配Bean,可能导致JobStatusService处于高水平。

尝试在MongoJobStatusService和JobStatusService之间添加其他接口,如下所示

public class MongoJobStatusService implements IMongoJobStatusService  {
..}

public interface IMongoJobStatusService  implements  JobStatusService<MongoJobStatus> {
...
}

我有同样的问题(Spring autowire trouble with generic parameter),我就这样解决了......