0

我正在使用最新版本的 Spring,当我尝试两次注入相同的泛型类型并且泛型类型的实现使用缓存时,我遇到了启动错误。

下面是我可以创建的最简单的示例来复制错误。

// build.gradle dependencies
dependencies {
    compile 'org.springframework.boot:spring-boot-starter'
    compile 'org.springframework.boot:spring-boot-starter-web'
}
// MyApplication.java
@SpringBootApplication
@EnableCaching
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager();
    }
}
// HomeController.java
@RestController
@RequestMapping(value = "/home")
public class HomeController {

    @Autowired
    public HomeController(
        GenericService<String> s1,
        GenericService<String> s2, // <-- Notice GenericService<String> twice
        GenericService<Integer> s3
    ) {}
}
// GenericService.java
public interface GenericService<T> {
    public T aMethod();
}
// IntegerService.java
@Service
public class IntegerService implements GenericService<Integer> {

    @Override
    @Cacheable("IntegerMethod")
    public Integer aMethod() {
        return null;
    }
}
// StringService.java
@Service
public class StringService implements GenericService<String> {

    @Override
    @Cacheable("StringMethod")
    public String aMethod() {
        return null;
    }
}

这编译得很好,但是当我运行应用程序时,我收到以下错误:

No qualifying bean of type [demo.GenericService] is defined: expected single matching bean but found 2: integerService,stringService

我还没有尝试过使用限定符,但我猜这将是一种解决方法。我会在发布后尝试一下。理想情况下,我希望自动装配泛型和缓存以集成开箱即用。我做错了什么,或者我能做些什么来让它工作吗?

谢谢!

4

1 回答 1

0

如果您不想在构造函数中使用 @Qualifier 并仍然使用接口,您可以在服务声明中添加一个值。

@Service(value = "integerService")
public class IntegerService implements GenericService<Integer> {

    @Override
    @Cacheable("IntegerMethod")
    public Integer aMethod() {
        return 42;
    }
}

@Service(value = "stringService")
public class StringService implements GenericService<String> {

    @Override
    @Cacheable("StringMethod")
    public Integer aMethod() {
        return 42;
    }
}

可以肯定的是,我用 Spring-Boot 创建了一个项目,编译并运行了它。所以上面应该工作。它与您已经在做的基本相同,但打字更少。

我之前的答案(修改之前)是做这样的事情:

// HomeController.java
@RestController
@RequestMapping(value = "/home")
public class HomeController {

    @Autowired
    public HomeController(
        StringService s1,
        StringService s2, 
        IntegerService s3
    ) {}
}

但是您必须不实现接口才能使其工作。

于 2015-05-28T22:04:11.733 回答