Spring 4具有缓存和通用类型自动装配

时间:2015-05-28 20:20:56

标签: spring spring-boot spring-cache spring-ioc

我使用最新版本的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

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

谢谢!

1 个答案:

答案 0 :(得分: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
    ) {}
}

但你必须不实现接口才能使其发挥作用。