【问题标题】:Autowiring any of an Interface using Spring Boot使用 Spring Boot 自动装配任何接口
【发布时间】:2020-04-14 09:08:25
【问题描述】:

我想自动装配一个在组件中实现的类。这是界面的一部分:

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GenericResourceHandlerService<T extends ResourceRequest, A extends ResultType, B extends ResourceService<T, A>> {

    private final B service;

    public Response get(String x) {
        various checks(x, service.getType());

        B res = service.get(x);

        if (res!= null) {
            return Response.status(Response.Status.OK).entity(res).build();
        } else {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }
}

那么,实现 ResourceService 的类将如下所示:

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TypeOneService implements EntityService<CityRequest, City> {

    private final Repository repository;

    @Override
    public ResultType getType() {
        return ResultType.TYPE_ONE;
    }

    @Timed
    public TYPE_ONE get(String resource) {
        return repository.get(resource);
    }

}

界面本身看起来是这样的:

public interface EntityService<T extends EntityRequest, A extends ReturnableEntity> {

    ResourceType getResourceType();

    A get(String resource);

}

现在,我有一组控制器尝试自动连接 GenericResourceHandlerService 并调用它的 get 方法。看起来像这样:

public class TypeOneController {

    private final TypeOneService typeOneService;

    private final GenericResourceHandlerService<TypeOneRequest, TypeOne, TypeOneService> genericResourceHandlerService;

    public Response getListItemByResource(
        String resource
    ) {
        return genericResourceHandlerService.get(resource);
    }
}

或者这个:

public class TypTwoController {

    private final TypeTwoService typeTwoService;

    private final GenericResourceHandlerService<TypeTwoRequest, TypeTwo, TypeTwoService> genericResourceHandlerService;

    public Response getListItemByResource(
        String resource
    ) {
        return genericResourceHandlerService.get(resource);
    }
}

这会编译,但是当应用程序启动时,我会收到以下错误消息:

Parameter 0 of constructor in path.GenericResourceHandlerService required a single bean, but 2 were found:
    - typeOneSerivce: defined in file [C:\Path\TypeOneService.class]
    - typeTwoService: defined in file [C:\Path\TypeTwoService.class]

我认为这是因为 Spring Boot 无法确定要使用哪个服务来自动装配。我想做的事有可能吗?

【问题讨论】:

  • 你必须使用@Qualifier注解来满足这种需求。
  • @Sambit 在哪里?我需要在控制器类上做一些事情,因为这是自动装配完成的地方。
  • 查看此链接。memorynotfound.com/…

标签: java spring spring-boot


【解决方案1】:

Spring 尝试注入一个 bean 来解析 GenericResourceHandlerService.service,但服务的类型为 B 并且 B 扩展了 ResourceService。 Spring 发现 2 个 bean 实现了这个接口,所以不知道要自动装配哪个实现..

您可以将@Qualifier 放在字段service 上,但我想您会失去这种类型GenericResourceHandlerService 的通用性

也许最好的方法是让控制器通过GenericResourceHandlerService 中的实现,并让它作为一个简单的pojo..而不是spring bean(所以删除GenericResourceHandlerService 上的@Service

这样

public class TypeOneController {

@Autowired
private final TypeOneService typeOneService;

private final GenericResourceHandlerService<TypeOneRequest, TypeOne, TypeOneService> genericResourceHandlerService = new GenericResourceHandlerService(typeOneService);

public Response getListItemByResource(
    String resource
) {
    return genericResourceHandlerService.get(resource);
}

}

【讨论】:

    猜你喜欢
    • 2018-12-03
    • 1970-01-01
    • 2015-05-27
    • 2019-01-16
    • 2011-01-24
    • 2017-09-07
    • 1970-01-01
    • 2014-06-24
    • 2019-05-03
    相关资源
    最近更新 更多