多Bean依赖时如何自动装配?如何指定Bean实例初始化ClassA对象
好问题!当同一个类型存在多个Spring Bean实例时,默认的按类型自动装配就会失效——Spring不知道该选哪一个。针对你的需求,我给你两种最常用的解决方案,都能完美实现让obj1绑定instance1、obj2绑定instance2的效果:
方案1:配置类中定义绑定不同ClassB的ClassA实例
这种方法最清晰,直接在配置类里为每个ClassA实例指定要注入的ClassB,然后在测试类中通过名称或@Qualifier选择对应的ClassA。
首先修改你的TestConfig,添加两个ClassA的Bean,分别注入instance1和instance2:
@Configuration class TestConfig { @Bean(name = "instance1") public ClassB instance1() { return new ClassB(); } @Bean(name = "instance2") public ClassB instance2() { return new ClassB(); } // 绑定instance1的ClassA实例 @Bean("classAWithInstance1") public ClassA classAWithInstance1(@Qualifier("instance1") ClassB classB) { ClassA classA = new ClassA(); classA.classB = classB; // 如果ClassB是私有字段,建议改用构造器注入或setter方法 return classA; } // 绑定instance2的ClassA实例 @Bean("classAWithInstance2") public ClassA classAWithInstance2(@Qualifier("instance2") ClassB classB) { ClassA classA = new ClassA(); classA.classB = classB; return classA; } }
然后在测试类中,用@Qualifier指定要注入的ClassA Bean:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = TestConfig.class) class Test { @Autowired @Qualifier("classAWithInstance1") ClassA obj1; // 内部的ClassB是instance1 @Autowired @Qualifier("classAWithInstance2") ClassA obj2; // 内部的ClassB是instance2 }
方案2:使用@Resource注解按名称装配
如果不想修改配置类,也可以通过@Resource(天生支持按名称匹配)来实现。不过这种方法需要调整ClassA的注入逻辑,并且同样需要为不同的绑定关系创建独立的ClassA Bean:
先修改ClassA的注入方式,允许外部指定要绑定的ClassB名称:
class ClassA { private ClassB classB; // 提供构造器注入,方便配置类指定具体的ClassB实例 public ClassA(ClassB classB) { this.classB = classB; } }
然后在配置类中创建ClassA Bean时,直接传入对应的ClassB实例(和方案1的配置类逻辑一致),测试类的写法也和方案1完全相同。
额外说明
Spring默认的@Autowired是按类型装配的,当ClassB存在多个Bean实例时,Spring无法自动确定要注入哪一个,就会抛出NoUniqueBeanDefinitionException。上面的方案本质都是通过明确指定Bean的名称或限定符,告诉Spring该选择哪一个实例。
内容的提问来源于stack exchange,提问作者iAmLearning
相关产品推荐
相关产品推荐

