Spring自动装配参数化的泛型类型 [英] Spring autowiring parameterized generic types

查看:488
本文介绍了Spring自动装配参数化的泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

 界面JobStatusService< S扩展JobStatus> {
S beginJob(...);
S updateJobStatus(S targetJob,Status newStatus);
void finishJob(S targetJob);





$ b相应地,我的Spring控制器可以处理关闭作业并记录回发的外观喜欢这个;控制器类携带一个类型参数,以便我可以存储新的状态对象并将其传递回服务:

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

...处理方法...
JS status = jobService.createJob(info,go,here);
//通过HTTP提交作业
jobService.updateJobStatus(status,Status.PROCESSING);
...
}

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

  public class MongoJobStatusService实现JobStatusService< MongoJobStatus> {
MongoJobStatus beginJob(...){...}
MongoJobStatus updateJobStatus(MongoJobStatus作业,状态newStatus){...}
}

当我尝试启动时,Spring上下文失败, NoSuchBeanDefinitionException 代替 JobStatusService 。我已经证实,如果我设置了 required = false ,那么 MongoJobStatusService bean被正确的组件扫描并安装在上下文中,但Spring似乎无法理解该类实现了该参数化的泛型接口。



有什么办法可以指定Spring需要一个bean实现一个类型参数的泛型接口,它在包含bean级别参数化,而不是在字段级别嵌入为字面类型参数?

Spring容器似乎无法解析控制器类上的可接受类型参数,但如果明确提供了这些类型参数,它可以解决注入字段。通过继承控制器类的字面类型,我已经能够非常理想地解决这个问题:

  @Controller 
公共类MongoJobController< MongoJobStatus> {}

我有为此打开了一个JIRA问题,并且 GitHub上的一个简单示例


Spring 4 included major enhancements to generic type resolution, but I'm having trouble with autowiring a generic type when the type argument is parameterized on the containing bean class.

I am needing to track the status of jobs submitted to an outside service, and I want to create an entry for each job when it starts and clear or update it when I receive postbacks. I generally try to keep my persistence strategy separated from the service interface, so I have an interface JobStatus and a Spring Data Mongo class MongoJobStatus implements JobStatus. Since a job might fail before the outside service gets a chance to assign it an ID (e.g., an HTTP 502), I need to pass the JobStatus back to the service to identify for updates:

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

Accordingly, my Spring controller that handles firing off the jobs and recording the postbacks looks like this; the controller class carries a type parameter so that I can store the new status object and pass it back to the service:

@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);
    ...
}

My MongoDB-backed implementation looks like this:

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

When I try to launch, the Spring context fails with NoSuchBeanDefinitionException for JobStatusService. I have confirmed that if I set required=false, the MongoJobStatusService bean is properly component-scanned and installed in the context, but Spring doesn't seem to be able to understand that the class implements that parameterized generic interface.

Is there any way to specify to Spring that I need a bean implementing a generic interface with a type argument that is parameterized at the containing bean level instead of embedded as a literal type argument on the field level?

解决方案

The Spring container does not appear to be able to solve for acceptable type parameters on the controller class, but it can solve for the injected field if those type parameters are supplied explicitly. I have been able to suboptimally work around the problem by subclassing the controller class with a literal type:

@Controller
public class MongoJobController<MongoJobStatus> {}

I have opened a JIRA issue for this and have a minimal example on GitHub.

这篇关于Spring自动装配参数化的泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆