You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

依赖注入:如何避免向AccountValidator这类有状态对象隐藏依赖?

场景解决方案分析

一、可选应对方案

1. 工厂模式(原方案)

通过注入工厂类明确依赖,测试时可mock工厂返回自定义AccountValidator。缺点是会新增工厂类,但如果这类动态创建实例的场景不多,该方案逻辑清晰,维护成本可控。

2. 利用Spring内置的ObjectProvider/Provider

借助Spring原生的ObjectProvider(或JSR-330的Provider)延迟获取实例,无需手写工厂类,既能保持依赖注入的透明性,又能满足动态创建对象的需求。

3. 将AccountValidator设为原型Bean

把AccountValidator配置为原型作用域,每次获取都是新实例,结合构造参数注入实现Spring托管,同时适配有状态实例的创建需求。

4. 重构为无状态工具类

若业务逻辑允许,将AccountValidator改为无状态设计,把Account作为方法参数传入,直接注入单例Bean即可,这是最简洁的实现方式。

二、偏好方案

优先推荐无状态工具类改造(若业务允许),其次是原型Bean+ObjectProvider方案,原因如下:

  • 避免额外工厂类的编写,减少类泛滥问题;
  • 所有依赖通过构造注入声明,符合Spring最佳实践,单元测试时mock更便捷;
  • 完全利用Spring容器能力,无需维护自定义逻辑。

三、将AccountValidator设为Spring托管的具体实现

情况1:业务允许改为无状态(推荐)

将AccountValidator改为无状态,校验逻辑通过方法参数接收Account,注册为单例Bean:

@Component
class AccountValidator {
    public boolean isValid(Account account) {
        // 原校验逻辑,不再持有Account成员变量
        ...
    }
}

// MyService直接注入AccountValidator
@Component
class MyService {
    private final AusiliaryService ausService;
    private final AccountValidator accountValidator;

    public MyService(AusiliaryService ausService, AccountValidator accountValidator) {
        this.ausService = ausService;
        this.accountValidator = accountValidator;
    }

    public boolean isAccountValid(Account account) {
        boolean isValid = accountValidator.isValid(account);
        if(isValid) {
            ausService.openAccount(account);
        }
        return isValid;
    }
}

情况2:必须保持有状态(持有Account实例)

将AccountValidator设为原型作用域,通过ObjectProvider动态获取实例:

  1. 定义有状态的AccountValidator:
class AccountValidator {
    private final Account account;

    public AccountValidator(Account account) {
        this.account = account;
    }

    public boolean isValid() {
        // 使用成员变量account执行校验
        ...
    }
}
  1. 在配置类中注册原型Bean:
@Configuration
class AppConfig {
    @Bean
    @Scope("prototype")
    public AccountValidator accountValidator(Account account) {
        return new AccountValidator(account);
    }
}
  1. MyService中注入ObjectProvider获取实例:
@Component
class MyService {
    private final AusiliaryService ausService;
    private final ObjectProvider<AccountValidator> accountValidatorProvider;

    public MyService(AusiliaryService ausService, ObjectProvider<AccountValidator> accountValidatorProvider) {
        this.ausService = ausService;
        this.accountValidatorProvider = accountValidatorProvider;
    }

    public boolean isAccountValid(Account account) {
        // 传入构造参数,获取原型实例
        AccountValidator accountValidator = accountValidatorProvider.getObject(account);
        boolean isValid = accountValidator.isValid();
        if(isValid) {
            ausService.openAccount(account);
        }
        return isValid;
    }
}

内容的提问来源于stack exchange,提问作者GionJh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 19:33:25