Spring Boot泛型组件注入问题:如何解决Mapper多Bean冲突?
解决方案
当然可以解决这个问题,核心原因是Java泛型擦除机制导致Spring无法通过泛型类型自动区分不同的Mapper实现类,当容器中存在多个Mapper类型的Bean时,Spring无法确定ListMapper构造函数该注入哪一个,从而抛出NoUniqueBeanDefinitionException。下面是两种直接可行的解决办法:
方案一:手动创建泛型ListMapper实例(推荐)
先移除ListMapper类上的@Component注解,然后在配置类中为每种泛型组合手动创建对应的ListMapper Bean,明确绑定对应的Mapper实现类:
// 移除ListMapper的@Component注解 public final class ListMapper<FROM, TO> { private final Mapper<FROM, TO> mapper; public ListMapper(Mapper<FROM, TO> mapper) { this.mapper = mapper; } public List<TO> mapList(final List<FROM> data) { if (data == null) return null; return data.stream() .map(mapper::map) .collect(Collectors.toList()); } } // 新增配置类 @Configuration public class ListMapperConfig { // 为Foo1→Bar1的类型组合创建ListMapper Bean @Bean public ListMapper<Foo1, Bar1> foo1Bar1ListMapper(Foo1ToBar1Mapper mapper) { return new ListMapper<>(mapper); } // 为Foo2→Bar2的类型组合创建ListMapper Bean @Bean public ListMapper<Foo2, Bar2> foo2Bar2ListMapper(Foo2ToBar2Mapper mapper) { return new ListMapper<>(mapper); } // 第三个泛型组合同理 @Bean public ListMapper<Foo3, Bar3> foo3Bar3ListMapper(Foo3ToBar3Mapper mapper) { return new ListMapper<>(mapper); } }
Spring 4.0及以上版本支持基于泛型类型的Bean匹配,注入时会自动根据泛型参数找到对应的ListMapper实例,比如MyClass1中注入ListMapper<Foo1, Bar1>时,会匹配到foo1Bar1ListMapper这个Bean。
方案二:使用@Qualifier限定符匹配
如果希望保留ListMapper的@Component注解,可以给每个Mapper实现类添加唯一的@Qualifier标识,然后通过配置类创建ListMapper时指定对应的限定符:
步骤1:给Mapper实现类添加@Qualifier
@Component @Qualifier("foo1Bar1Mapper") public class Foo1ToBar1Mapper implements Mapper<Foo1, Bar1> { @Override public Bar1 map(Foo1 from) { // 实现转换逻辑 } } @Component @Qualifier("foo2Bar2Mapper") public class Foo2ToBar2Mapper implements Mapper<Foo2, Bar2> { @Override public Bar2 map(Foo2 from) { // 实现转换逻辑 } }
步骤2:在配置类中绑定限定符与ListMapper
@Configuration public class ListMapperConfig { @Bean public ListMapper<Foo1, Bar1> foo1Bar1ListMapper(@Qualifier("foo1Bar1Mapper") Mapper<Foo1, Bar1> mapper) { return new ListMapper<>(mapper); } @Bean public ListMapper<Foo2, Bar2> foo2Bar2ListMapper(@Qualifier("foo2Bar2Mapper") Mapper<Foo2, Bar2> mapper) { return new ListMapper<>(mapper); } }
这种方式和方案一本质类似,只是通过限定符明确指定了依赖的Mapper实现类,同样能解决Bean冲突问题。
内容的提问来源于stack exchange,提问作者JerryThePineapple
相关产品推荐
相关产品推荐

