使用JobRunr调度抽象类子类Lambda任务时遇Bean冲突问题求助
JobRunr调度任务遇到NoUniqueBeanDefinitionException的解决方向
你当前的代码在使用JobRunr结合Spring调度任务时触发了org.springframework.beans.factory.NoUniqueBeanDefinitionException,异常核心原因是Spring容器中存在Task1、Task2两个Task类型的实现类,无法确定要注入的唯一Bean。你的推测——JobRunr序列化时识别抽象类而非具体子类——是准确的,以下是具体解决思路:
解决方向
1. 直接调度具体子类Bean
放弃通过抽象类列表调用的方式,直接注入并引用具体的子类实例,从根源避免多态带来的序列化和Bean注入问题:
@Component public class TaskExecutionListener implements ApplicationListener<TaskEvent> { private final Task1 task1; private final Task2 task2; // 构造注入具体子类Bean public TaskExecutionListener(Task1 task1, Task2 task2) { this.task1 = task1; this.task2 = task2; } @Override public void onApplicationEvent(TaskEvent event) { // 直接调度具体子类的process方法 BackgroundJob.enqueue(() -> task1.process()); } }
2. 配置JobRunr序列化支持多态类型
如果必须保留抽象类的设计,需要配置JobRunr的序列化机制,让它能正确识别并序列化具体子类:
- 给抽象类
Task添加Jackson多态注解,明确子类类型:import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonSubTypes; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = Task1.class, name = "task1"), @JsonSubTypes.Type(value = Task2.class, name = "task2") }) abstract class Task { abstract void process(); } - 配置JobRunr使用Jackson作为序列化器,确保Spring能正确反序列化具体子类:
@Bean public JobScheduler jobScheduler(JacksonJsonSerializer jacksonJsonSerializer, DataSource dataSource, ApplicationContext applicationContext) { return JobRunr.configure() .useJobActivator(new SpringJobActivator(applicationContext)) .useJsonSerializer(jacksonJsonSerializer) .useStorageProvider(SqlStorageProviderFactory.sqlStorageProvider(dataSource)) .initialize() .createJobScheduler(); }
3. 避免在Lambda中引用集合元素
你当前代码中tasks.get(0)引用的是集合中的抽象类实例,JobRunr序列化时无法精准识别具体子类,Spring在恢复Bean时就会因为找不到唯一TaskBean报错。建议直接引用具体Bean实例,而非集合中的抽象类对象。
内容的提问来源于stack exchange,提问作者Alex Schmidt
相关产品推荐
相关产品推荐

