java - 在抽象类的具体类中 Autowiring 而不是实现接口(interface)

标签 java spring-boot interface abstract-class autowired

我正在使用 Spring boot,并且有以下任务模型

public class Task {
    private String name;
    private TaskType type; // ManualTask, AutomatedTask
    private boolean completed;
    //....other fields

    //getters and setters
}

Controller

@Controller
@RequestMapping("/api/task")
public class TaskController {

    @Autowired
    private TaskService taskService;

    @GetMapping("/{taskId}/handle")
    public String handle(Model model, @PathVariable("taskId") Long taskId) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        try {
            Task task = taskService.handle(taskId);
            model.addAttribute("task", task);
        } catch (Exception e) {
            return "errorpage";
        }
        return "successpage";
    }
}

我有一个界面

public interface TaskService {

    Task findById(Long taskId);

    Task handleTask(Long taskId) throws ClassNotFoundException, InstantiationException, IllegalAccessException;

}

抽象类实现接口(interface):

@Service
public abstract class TaskServiceImpl implements TaskService {

    @Autowired
    private TaskRepository taskRepository;

    private static final String PATH_OF_CLASS = "com.task.service.impl";

    protected abstract Task doTypeSpecificTask(Long taskId);

    @Override
    public Task findById(Long taskId) {
        return taskRepository.findById(taskId).get();
    }

    @Override
    public Task handleTask(Long taskId) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Task task = findById(taskId);
        TaskServiceImpl service = getHandlerService(task);
        return service.doTypeSpecificTask(taskId);
    }

    private TaskServiceImpl getHandlerService(Task task) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        String serviceClassName = PATH_OF_CLASS.concat(".").concat(task.getTaskType().getName()).concat("Service");
        Class<?> serviceClass = Class.forName(serviceClassName);
        if (!TaskServiceImpl.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Service class " + serviceClassName + " did not implements " + TaskServiceImpl.class.getName());
        }
        Object serviceObject = serviceClass.newInstance();
        TaskServiceImpl service = (TaskServiceImpl) serviceObject;
        return service;
    }


}

以及扩展抽象类的具体服务

@Service
@Primary
public class ManualTaskService extends TaskServiceImpl {

    @Autowired
    private TaskRepository taskRepository;

    @Autowired
    private ManualTaskHandlerService manualTaskHandlerService;

    @Override
    protected Task doTypeSpecificTask(Long taskId) {
        Task task = findById(taskId);
        manualTaskHandlerService.handleManualTask(task);
        task.setCompleted(true);
        return taskRepository.save(task);
    }
}

@Service
public class AutomatedTaskService extends TaskServiceImpl {

    @Autowired
    private TaskRepository taskRepository;

    @Autowired
    private AutomatedTaskHandlerService automatedTaskHandlerService;

    @Override
    protected Task doTypeSpecificTask(Long taskId) {
        Task task = findById(taskId);
        automatedTaskHandlerService.handleAutomatedTask(task);
        task.setCompleted(true);
        return taskRepository.save(task);
    }
}

public interface TaskRepository extends JpaRepository<Task, Long> {

}

根据运行时任务的类型动态选择ManualTask​​ServiceAutomatedTaskService

现在,如果没有 @Primary,我会收到以下错误:

Field taskService in com.test.controller.TaskController required a single bean, but 2 were found:
- manualTaskService
- automatedTaskService

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

在ManualTask​​Service中设置@Primary后,ManualTask​​Service中的doTypeSpecificTask可以工作,但在AutomatedTaskService中由于automatedTaskHandlerService.handleAutomatedTask(task)而失败。从 AutomatedTaskService 调用 taskRepository 也会失败。

我尝试使用@Qualifier以及将抽象类中的所有@Autowired定义为 protected ,但没有任何效果。我做错了什么?

最佳答案

每个限定符应该有不同的名称:

@Autowired
@Qualifier("manualTaskService")
private TaskServiceImpl manualTaskService;

@Autowired
@Qualifier("automatedTaskService")
private TaskServiceImpl automatedTaskService;

在服务中定义:

@Service("manualTaskService")
public class ManualTaskService extends TaskServiceImpl {

@Service("automatedTaskService")
public class AutomatedTaskService extends TaskServiceImpl {

关于java - 在抽象类的具体类中 Autowiring 而不是实现接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53850686/

相关文章:

java.nio.file 无法复制文件

java - 如何使用java在多线程中使用log4j?

spring-boot - 如何使用 OpenApi 自定义 swagger-ui.html url

java - 使用 class.cast 转换从 Redis 接收的对象失败,使用 ObjectMapper.convertValue 工作

java - Spring Boot 2.0 迁移后 : jdbcUrl is required with driverClassName

c# - 您应该为接口(interface)、具体实现或两者编写 XML 注释吗?

c# - 如何对 iList 进行排序(使用或不使用 linq)

java - 如何将外部源的上下文添加到 Kafka Streams 中的记录的正确方法

java - 连接两个java项目

java - 为什么方法返回接口(interface)类型的对象?