Java中 如何让抽象类通过依赖注入为子类提供公共 Service

作者:袖梨 2026-07-26
抽象类不能被Spring直接实例化,因此不可作为Bean注入;但可通过子类继承并标注@Service等注解,使Spring在创建子类时自动注入父类中声明的protected依赖,推荐使用构造器注入以提升可测试性与清晰度。

抽象类本身不能被 Spring 直接实例化,因此不能直接作为 Bean 注入。但你可以在抽象类中声明依赖(如 Service),并通过子类继承 + Spring 的依赖注入机制,让子类在初始化时自动获得这些公共 Service。

抽象父类中定义 Service 字段并提供 protected 访问

在抽象类里用 @Autowired 注入 Service,并设为 protected,这样子类可直接使用:

public abstract class BaseService {    @Autowired    protected UserService userService;    @Autowired    protected OrderService orderService;    // 可选:提供模板方法或通用逻辑    public void doCommonLogic() {        System.out.println("Using " + userService.getClass().getSimpleName());    }}

子类继承抽象类并标注为 Spring Bean

子类必须是 Spring 管理的 Bean(如 @Service@Component),Spring 才会在创建子类实例时完成字段注入:

  • 子类无需重复写 @Autowired,父类的 protected 字段会被自动注入
  • 确保子类有默认构造函数(或无参构造),否则 Spring 构造注入可能失败
  • 如果子类也需额外依赖,可继续用 @Autowired 或构造器注入
@Servicepublic class UserOrderService extends BaseService {    public void processUserOrder(Long userId) {        User user = userService.findById(userId); // 直接使用父类注入的 service        // ... 业务逻辑    }}

更推荐:用构造器注入提升可测试性与清晰度

避免字段注入的隐式依赖,建议在抽象类中定义带参构造器,子类通过构造器传递依赖:

立即学习“Java免费学习笔记(深入)”;

  • 抽象类不加 @Autowired,而是接收依赖作为构造参数
  • 子类在自己的构造器中调用 super(...),并由 Spring 自动装配
  • 这样既保证依赖不可变,又便于单元测试(可手动 new 实例传 mock)
public abstract class BaseService {    protected final UserService userService;    protected final OrderService orderService;    public BaseService(UserService userService, OrderService orderService) {        this.userService = userService;        this.orderService = orderService;    }}@Servicepublic class UserOrderService extends BaseService {    public UserOrderService(UserService userService, OrderService orderService) {        super(userService, orderService);    }}

注意:抽象类本身不注册为 Bean

Spring 不会(也不能)将 @Component@Service 加在抽象类上——这会导致启动报错。抽象类只是代码复用和依赖声明的载体,真正被 IoC 容器管理的是它的具体子类。

只要子类是合法的 Spring Bean,且依赖项已正确定义(如 @Service 标注的实现类),Spring 就能完成整个继承链上的依赖注入。

相关文章

精彩推荐