含继承与抽象类的Spring构造器Bean注入代码优化咨询
解决方案
1. 抽象类层面统一注入依赖
既然所有继承B的类都依赖ServiceA的唯一实现z,以及ServiceB的x实现,直接在抽象类B的构造器中完成注入配置,子类无需重复写@Qualifier:
抽象类B的代码
public abstract class B extends A { protected B(ServiceA serviceA, @Qualifier("x") ServiceB serviceB) { super(serviceA, serviceB); } }
子类D的简化实现
@Component public class D extends B { // 直接复用父类构造器,无需任何额外注解 public D(ServiceA serviceA, ServiceB serviceB) { super(serviceA, serviceB); } }
同理处理抽象类C,统一注入z和y:
public abstract class C extends A { protected C(ServiceA serviceA, @Qualifier("y") ServiceB serviceB) { super(serviceA, serviceB); } }
后续新增B/C的子类时,只需要编写调用父类构造器的代码即可,完全不用手动添加限定符配置。
2. 进阶优化:用自定义限定符替代字符串
如果觉得字符串"x"、"y"不够类型安全,容易写错,可以自定义限定符注解进一步优化:
自定义限定符注解
@Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface UseServiceBX { } @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface UseServiceBY { }
给ServiceB的实现类标记注解
@Service @UseServiceBX public class X implements ServiceB { // 业务代码 } @Service @UseServiceBY public class Y implements ServiceB { // 业务代码 }
修改抽象类的构造器
public abstract class B extends A { protected B(ServiceA serviceA, @UseServiceBX ServiceB serviceB) { super(serviceA, serviceB); } } public abstract class C extends A { protected C(ServiceA serviceA, @UseServiceBY ServiceB serviceB) { super(serviceA, serviceB); } }
这样不仅避免了字符串硬编码的风险,子类的代码依然保持简洁,新增子类时零额外配置。
原理说明
Spring处理子类构造器注入时,会自动解析父类构造器上的依赖注解。当子类构造器调用父类构造器时,Spring会根据父类构造器的限定符规则匹配对应的Bean,子类无需重复声明依赖规则。
内容的提问来源于stack exchange,提问作者Saif
相关产品推荐
相关产品推荐

