如何在父类中注入使用不同qualifier的SessionFactory的ChildClass Bean?
当然可以实现!你想要在父类里拥有两个分别绑定SessionFactory A和SessionFactory B的ChildClass实例,Spring提供了好几种灵活的方案,我给你详细拆解一下:
核心前提:先创建不同的ChildClass Bean实例
首先要明确:同一个ChildClass类要生成两个不同的Bean,分别对应不同的SessionFactory,我们需要通过配置类来显式定义这两个Bean:
@Configuration public class BeanConfig { // 定义第一个SessionFactory Bean,标识为"A" @Bean("sessionFactoryA") public SessionFactory sessionFactoryA() { // 这里写SessionFactory A的具体配置逻辑 return new SessionFactory(); } // 定义第二个SessionFactory Bean,标识为"B" @Bean("sessionFactoryB") public SessionFactory sessionFactoryB() { // 这里写SessionFactory B的具体配置逻辑 return new SessionFactory(); } // 基于SessionFactory A创建ChildClass实例,标识为"childA" @Bean("childA") public ChildClass childClassA(@Qualifier("sessionFactoryA") SessionFactory sessionFactory) { return new ChildClass(sessionFactory); } // 基于SessionFactory B创建ChildClass实例,标识为"childB" @Bean("childB") public ChildClass childClassB(@Qualifier("sessionFactoryB") SessionFactory sessionFactory) { return new ChildClass(sessionFactory); } }
这段代码的作用是:先生成两个带名称标识的SessionFactory Bean,再分别用它们初始化两个ChildClass Bean,并给这两个ChildClass也加上名称标识。
方案1:@Autowired + @Qualifier 字段注入
在父类中,通过@Autowired配合@Qualifier指定要注入的具体ChildClass实例:
class ParentClass { // 注入绑定SessionFactory A的ChildClass实例 @Autowired @Qualifier("childA") private ChildClass childClassA; // 注入绑定SessionFactory B的ChildClass实例 @Autowired @Qualifier("childB") private ChildClass childClassB; // 后续就可以分别使用这两个实例了 }
@Qualifier的作用就是告诉Spring:不要随便找一个ChildClass Bean,要找名称为childA/childB的那个。
方案2:@Resource 按名称注入
如果你觉得写两个注解麻烦,可以用@Resource注解(它是JSR-250标准注解,Spring完全支持),它默认按Bean的名称匹配:
class ParentClass { @Resource(name = "childA") private ChildClass childClassA; @Resource(name = "childB") private ChildClass childClassB; }
这种写法更简洁,效果和方案1完全一致。
方案3:构造注入(推荐!符合Spring最佳实践)
如果追求代码的可测试性和不可变性,更推荐用构造注入的方式,把依赖都放在构造器里:
class ParentClass { private final ChildClass childClassA; private final ChildClass childClassB; // 构造器中通过@Qualifier指定要注入的Bean public ParentClass(@Qualifier("childA") ChildClass childClassA, @Qualifier("childB") ChildClass childClassB) { this.childClassA = childClassA; this.childClassB = childClassB; } }
这种方式不需要在字段上加任何注解,Spring会自动解析构造器参数并注入对应的Bean。而且用final修饰字段,能保证实例的不可变性,更符合面向对象的设计原则,也方便写单元测试的时候手动传入依赖。
补充说明
如果你的ChildClass原本是用@Component注解标记的(而不是通过@Bean定义),那默认只会生成一个ChildClass Bean,这种情况下是无法直接得到两个不同实例的。所以必须通过@Configuration类中的@Bean方法来显式创建多个ChildClass实例,这是实现需求的关键。
内容的提问来源于stack exchange,提问作者stackuser

