Java中如何实现类的部分参数依赖注入
Java实现部分依赖注入、部分参数手动传入的方案
针对你需要让HTTPWrapper类中HttpClient、DatabaseClient通过依赖注入获取,rootUrl、defaultHeaders由外部手动传入的需求,以下是几种可行的接地气方案:
方案1:工厂类(推荐,解耦且规范)
DI框架无法直接帮你完成"部分参数注入、部分手动传入"的构造方法调用,最清晰的方式是写一个工厂类,让工厂类负责注入需要的容器bean,对外提供创建HTTPWrapper的方法接收手动参数。
代码示例
// 工厂类,交给DI框架管理 @RequiredArgsConstructor(onConstructor = @__(@Inject)) public class HTTPWrapperFactory { // 这两个由DI框架注入 private final HttpClient httpClient; private final DatabaseClient databaseClient; // 对外暴露创建实例的方法,接收手动参数 public HTTPWrapper create(String rootUrl, String defaultHeaders) { return new HTTPWrapper(httpClient, databaseClient, rootUrl, defaultHeaders); } } // HTTPWrapper类,不需要DI注解,全参数构造保证不可变性 public class HTTPWrapper { private final HttpClient httpClient; private final DatabaseClient databaseClient; private final String rootUrl; private final String defaultHeaders; public HTTPWrapper(HttpClient httpClient, DatabaseClient databaseClient, String rootUrl, String defaultHeaders) { this.httpClient = httpClient; this.databaseClient = databaseClient; this.rootUrl = rootUrl; this.defaultHeaders = defaultHeaders; } // 你的业务方法... }
使用方式
在需要创建HTTPWrapper的地方,注入HTTPWrapperFactory,调用create方法传入自定义参数即可:
@Inject private HTTPWrapperFactory wrapperFactory; // 业务逻辑中创建实例 HTTPWrapper wrapper = wrapperFactory.create("https://api.example.com", "Content-Type: application/json");
方案2:手动从容器获取Bean(不推荐,耦合框架)
如果不想额外写工厂类,可以直接在使用处从DI容器中取出需要注入的Bean,再和手动参数一起传入构造方法。这种方式会耦合DI容器的API,代码不够优雅。
代码示例(以Spring为例)
// HTTPWrapper保持全参数构造 public class HTTPWrapper { private final HttpClient httpClient; private final DatabaseClient databaseClient; private final String rootUrl; private final String defaultHeaders; public HTTPWrapper(HttpClient httpClient, DatabaseClient databaseClient, String rootUrl, String defaultHeaders) { this.httpClient = httpClient; this.databaseClient = databaseClient; this.rootUrl = rootUrl; this.defaultHeaders = defaultHeaders; } } // 使用时从Spring容器获取Bean @Component public class BusinessService { private final ApplicationContext context; @Autowired public BusinessService(ApplicationContext context) { this.context = context; } public void execute() { HttpClient httpClient = context.getBean(HttpClient.class); DatabaseClient databaseClient = context.getBean(DatabaseClient.class); HTTPWrapper wrapper = new HTTPWrapper(httpClient, databaseClient, "https://api.example.com", "Content-Type: application/json"); // 调用wrapper的方法... } }
方案3:Setter方法补充手动参数(适合参数可变场景)
如果允许rootUrl和defaultHeaders不是不可变的,可以先通过DI注入HttpClient和DatabaseClient,再用Setter方法设置手动参数。这种方式要注意线程安全问题,且必须在调用业务方法前完成参数设置。
代码示例
@RequiredArgsConstructor(onConstructor = @__(@Inject)) public class HTTPWrapper { // 注入的参数设为final保证不可变 private final HttpClient httpClient; private final DatabaseClient databaseClient; // 手动传入的参数非final private String rootUrl; private String defaultHeaders; // Setter方法 public void setRootUrl(String rootUrl) { this.rootUrl = rootUrl; } public void setDefaultHeaders(String defaultHeaders) { this.defaultHeaders = defaultHeaders; } // 业务方法... }
使用方式
@Inject private HTTPWrapper httpWrapper; // 初始化时设置参数 public void init() { httpWrapper.setRootUrl("https://api.example.com"); httpWrapper.setDefaultHeaders("Content-Type: application/json"); }
内容的提问来源于stack exchange,提问作者Joe C.
相关产品推荐
相关产品推荐

