Spring无法自动assembly,有多个“类型的bean
这是我的问题:我有一个基本接口和两个实现类。
Service类对基接口有依赖关系,代码如下:
@Component public interface BaseInterface {}
@Component public class ClazzImplA implements BaseInterface{}
@Component public class ClazzImplB implements BaseInterface{}
配置是这样的:
@Configuration public class SpringConfig { @Bean public BaseInterface clazzImplA(){ return new ClazzImplA(); } @Bean public BaseInterface clazzImplB(){ return new ClazzImplB(); } }
服务类依赖于基接口将决定通过某些业务逻辑自动assembly哪个实现。代码如下:
@Service @SpringApplicationConfiguration(SpringConfig.class) public class AutowiredClazz { @Autowired private BaseInterface baseInterface; private AutowiredClazz(BaseInterface baseInterface){ this.baseInterface = baseInterface; } }
并且IDEA抛出exception:无法自动assembly。有多个BaseInterface
类型的bean。
虽然可以通过@ Qualifier来解决,但在这种情况下我无法选择依赖类。
@Autowired @Qualifier("clazzImplA") private BaseInterface baseInterface;
我试图阅读spring文档,它提供了一个Constructor-based dependency injection
但我仍然对这个问题感到困惑。
谁能帮我 ?
Spring在您在配置类中声明的两个bean之间混淆,因此您可以使用@Qualifier
注释和@Autowired
通过指定要连接的确切bean来消除混淆,在配置类上应用这些修改
@Configuration public class SpringConfig { @Bean(name="clazzImplA") public BaseInterface clazzImplA(){ return new ClazzImplA(); } @Bean(name="clazzImplB") public BaseInterface clazzImplB(){ return new ClazzImplB(); } }
然后在@autowired
注释
@Service @SpringApplicationConfiguration(SpringConfig.class) public class AutowiredClazz { @Autowired @Qualifier("the name of the desired bean") private BaseInterface baseInterface; private AutowiredClazz(BaseInterface baseInterface){ this.baseInterface = baseInterface; } }
仅使用spring框架无法解决这个问题。 您提到基于某些逻辑,您需要一个BaseInterface实例。 可以使用Factory Pattern解决此用例。 创建一个实际上是BaseInterface工厂的Bean
@Component public class BaseInterfaceFactory{ @Autowired @Qualifier("clazzImplA") private BaseInterface baseInterfaceA; @Autowired @Qualifier("clazzImplb") private BaseInterface baseInterfaceB; public BaseInterface getInstance(parameters which will decides what type of instance you want){ // your logic to choose Instance A or Instance B return baseInterfaceA or baseInterfaceB } }
配置(从另一个评论中无耻地复制)
@Configuration public class SpringConfig { @Bean(name="clazzImplA") public BaseInterface clazzImplA(){ return new ClazzImplA(); } @Bean(name="clazzImplB") public BaseInterface clazzImplB(){ return new ClazzImplB(); } }
服务类
@Service @SpringApplicationConfiguration(SpringConfig.class) public class AutowiredClazz { @Autowired private BaseInterfaceFactory factory; public void someMethod(){ BaseInterface a = factory.getInstance(some parameters); // do whatever with instance a } }
如果您使用@ @Autowired
,Spring会搜索与您要自动assembly的字段类型匹配的bean。 在您的情况下,有多个BaseInterface
类型的BaseInterface
。 这意味着Spring无法明确地选择匹配的bean。
在这种情况下,您没有其他选择来显式声明Spring应该使用的bean或解决歧义。
这里正确地回答说,在这种情况下,接口由多个类实现,我们必须使用@Component(name=$beanName)
命名每个bean。
我想补充一点,在这种情况下,Spring甚至可以在地图中自动assembly这样的bean:
@Autowired Map interfaceMap; //this will generate beans and index them with beanName as key of map