ObjectFactory核心是延迟获取Bean:不注入对象本身,而是注入能按需创建的工厂,将实例化时机推迟至调用getObject()时,从而解决启动开销大、循环依赖、作用域不匹配等问题。

在依赖注入中使用 ObjectFactory 延迟加载复杂 Bean,核心是“不直接拿对象,而是拿一个能随时取对象的工厂”,把创建时机从容器启动或注入时刻,推迟到真正调用 getObject() 的那一刻。
为什么需要 ObjectFactory 而不是直接 @Autowired
当 Bean 初始化开销大(如连接外部服务、加载大量配置、执行耗时初始化逻辑),或存在循环依赖、作用域不匹配(比如 singleton 依赖 prototype)等问题时,直接注入会导致:
- 启动变慢甚至失败(提前触发高成本初始化)
- Bean 创建卡在依赖链中(如 A→B→A 循环)
- 每次取到的都是同一个实例,无法适配 request/session 等短生命周期场景
ObjectFactory 绕过这些问题——它本身轻量,不触发目标 Bean 创建,只在你明确需要时才去容器里要。
三种常用注入方式
推荐优先使用构造器注入,兼顾清晰性与不可变性;字段注入适合快速验证;方法参数注入适用于临时、一次性的场景。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
构造器注入(推荐):
Service 类通过构造器接收 ObjectFactory,依赖关系一目了然,且避免 NPE 和循环依赖风险。
@Service<br>public class ReportGenerator {<br> private final ObjectFactory<DataSource> dataSourceFactory;<br><br> public ReportGenerator(ObjectFactory<DataSource> dataSourceFactory) {<br> this.dataSourceFactory = dataSourceFactory;<br> }<br><br> public void generate() {<br> DataSource ds = dataSourceFactory.getObject(); // 此刻才初始化<br> ds.query("...");<br> }<br>} -
字段注入(简洁但慎用):
适合原型 Bean 或调试阶段,但破坏封装性,不利于单元测试。
@Component<br>public class OrderProcessor {<br> @Autowired<br> private ObjectFactory<PaymentGateway> gatewayFactory;<br><br> public void handle(Order order) {<br> PaymentGateway gateway = gatewayFactory.getObject();<br> gateway.charge(order);<br> }<br>} -
方法参数注入(按需即取):
适用于 Controller 层等入口方法,避免将工厂长期持有,资源更可控。
@RestController<br>public class ApiController {<br> @GetMapping("/data")<br> public String fetchData(ObjectFactory<DataLoader> loaderFactory) {<br> return loaderFactory.getObject().load();<br> }<br>}
搭配 @Lazy 让延迟更彻底
@Lazy 注解可加在目标 Bean 定义上,确保即使被 ObjectFactory 获取,也**只在第一次 getObject() 时才真正创建实例**。两者配合效果最佳:
- 目标 Bean 加
@Lazy:跳过启动时实例化 - 引用方用
ObjectFactory:跳过注入时获取 - 二者叠加 = 启动零开销 + 使用才创建 + 单例复用(默认单例作用域下)
例如:
@Service<br>@Lazy // 关键:延迟整个 Bean 的首次创建<br>public class HeavyExternalClient {<br> public HeavyExternalClient() {<br> System.out.println("Connecting to remote service..."); // 启动时不执行<br> }<br>}
注意 ObjectFactory 和 ObjectProvider 的区别
如果需要更安全的取值(比如 Bean 可能不存在、或想提供默认行为),建议改用 ObjectProvider<T>:
-
getIfAvailable():Bean 不存在时不抛异常,返回 null -
getIfUnique():当有多个候选 Bean 时避免歧义 -
ifAvailable(...):空安全的消费式调用,写法更函数式
它兼容 ObjectFactory 接口,升级成本低,功能更强,Spring 5+ 更推荐使用。

















