1. 概述
本文将介绍 Google 开源的代码生成工具 AutoFactory。
它是一个编译期源码生成器,用于自动生成工厂类(Factory),帮助开发者避免手写大量重复的创建逻辑。对于熟悉依赖注入(DI)和 JSR-330 的项目来说,这简直是提效神器。
简单粗暴地说:你写个类,它帮你生成对应的工厂,连构造参数依赖都自动处理好,省时省力还少踩坑 ✅
2. Maven 配置
使用前先引入依赖:
<dependency>
<groupId>com.google.auto.factory</groupId>
<artifactId>auto-factory</artifactId>
<version>1.0-beta5</version>
</dependency>
🔍 最新版本可参考 Maven Central
⚠️ 注意:auto-factory
是编译期注解处理器,不需要运行时依赖,但某些 DI 框架(如 Guice)仍需手动引入。
3. 快速上手
我们以一个 Phone
类为例,看看 AutoFactory 能做什么。
基础用法
给类加上 @AutoFactory
,构造函数参数用 @Provided
标记需要由外部注入的依赖:
@AutoFactory
public class Phone {
private final Camera camera;
private final String otherParts;
public Phone(@Provided Camera camera, String otherParts) {
this.camera = camera;
this.otherParts = otherParts;
}
}
✅ @AutoFactory
:标记需要生成工厂的类
✅ @Provided
:表示该参数不由工厂传入,而是通过 Provider<T>
注入
编译后,AutoFactory 会自动生成如下工厂类:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public final class PhoneFactory {
private final Provider<Camera> cameraProvider;
@Inject
public PhoneFactory(Provider<Camera> cameraProvider) {
this.cameraProvider = checkNotNull(cameraProvider, 1);
}
public Phone create(String otherParts) {
return new Phone(
checkNotNull(cameraProvider.get(), 1),
checkNotNull(otherParts, 2)
);
}
}
使用方式也很直观:
PhoneFactory factory = new PhoneFactory(() -> new Camera("Sony", "SN001"));
Phone phone = factory.create("metal frame");
多构造函数支持
@AutoFactory
也可以直接标注在构造函数上,支持一个类有多个可生成的构造入口:
public class ClassicPhone {
private final String dialpad;
private final String ringer;
private String otherParts;
@AutoFactory
public ClassicPhone(@Provided String dialpad, @Provided String ringer) {
this.dialpad = dialpad;
this.ringer = ringer;
}
@AutoFactory
public ClassicPhone(String otherParts) {
this("defaultDialPad", "defaultRinger");
this.otherParts = otherParts;
}
}
对应生成两个 create
方法:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public final class ClassicPhoneFactory {
private final Provider<String> java_lang_StringProvider;
@Inject
public ClassicPhoneFactory(Provider<String> java_lang_StringProvider) {
this.java_lang_StringProvider = checkNotNull(java_lang_StringProvider, 1);
}
public ClassicPhone create() {
return new ClassicPhone(
checkNotNull(java_lang_StringProvider.get(), 1),
checkNotNull(java_lang_StringProvider.get(), 2)
);
}
public ClassicPhone create(String otherParts) {
return new ClassicPhone(checkNotNull(otherParts, 1));
}
}
支持 Qualifier 注解
AutoFactory 完全兼容 JSR-330 的 @Named
、@Qualifier
等注解,可用于区分不同实现:
@AutoFactory
public class Phone {
public Phone(@Provided @Named("Sony") Camera camera, String otherParts) {
// ...
}
}
生成的工厂会保留 @Named("Sony")
,便于 DI 容器识别:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public final class PhoneFactory {
@Inject
public PhoneFactory(@Named("Sony") Provider<Camera> cameraProvider) {
this.cameraProvider = cameraProvider;
}
// ...
}
这样在 Guice 或 Dagger 中就能精准绑定特定实现,避免冲突 ❌
4. 自定义工厂生成
AutoFactory 提供多个属性,可灵活控制生成逻辑。
4.1 自定义工厂类名
默认工厂名为 原类名 + Factory
,可通过 className
修改:
@AutoFactory(className = "SamsungFactory")
public class SmartPhone {
// ...
}
生成类名为 SamsungFactory
:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public final class SamsungFactory {
// ...
}
4.2 允许继承(非 final)
默认生成的工厂是 final
的,若需继承,设置 allowSubclasses = true
:
@AutoFactory(
className = "SamsungFactory",
allowSubclasses = true
)
public class SmartPhone {
// ...
}
生成结果变为普通类:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public class SamsungFactory {
// ...
}
4.3 实现接口
可通过 implementing
让工厂实现指定接口,前提是接口方法返回值为原类类型:
public interface CustomStorage {
SmartPhone customROMInGB(int romSize);
}
原类需有对应构造函数:
@AutoFactory(
className = "SamsungFactory",
allowSubclasses = true,
implementing = CustomStorage.class
)
public class SmartPhone {
public SmartPhone(int romSize) {
// ...
}
}
生成代码自动实现接口:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public class SamsungFactory implements CustomStorage {
public SmartPhone create(int romSize) {
return new SmartPhone(romSize);
}
@Override
public SmartPhone customROMInGB(int romSize) {
return create(romSize);
}
}
4.4 继承抽象类
使用 extending
可让工厂继承抽象类,要求抽象方法在目标类中有对应构造函数:
public abstract class AbstractFactory {
abstract CustomPhone newInstance(String brand);
}
@AutoFactory(extending = AbstractFactory.class)
public class CustomPhone {
public CustomPhone(String brand) {
// ...
}
}
生成结果:
@Generated("com.google.auto.factory.processor.AutoFactoryProcessor")
public final class CustomPhoneFactory extends AbstractFactory {
@Inject
public CustomPhoneFactory() {}
public CustomPhone create(String brand) {
return new CustomPhone(checkNotNull(brand, 1));
}
@Override
public CustomPhone newInstance(String brand) {
return create(brand);
}
}
AutoFactory 会自动将抽象方法桥接到 create(...)
,非常智能 ✅
5. 与 Guice 集成
AutoFactory 与 Guice 天然兼容,因为都基于 JSR-330。
添加 Guice 依赖
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.0</version>
</dependency>
绑定具体实现
假设我们希望 @Named("Sony")
的 Camera
由特定 Provider 提供:
public class SonyCameraModule extends AbstractModule {
private static int SONY_CAMERA_SERIAL = 1;
@Provides
@Named("Sony")
Camera provideSonyCamera() {
return new Camera("Sony", String.format("%03d", SONY_CAMERA_SERIAL++));
}
}
Guice 会自动注入匹配的 Provider<Camera>
到 PhoneFactory
构造函数中。
使用注入后的工厂
Injector injector = Guice.createInjector(new SonyCameraModule());
PhoneFactory factory = injector.getInstance(PhoneFactory.class);
Phone xperia = factory.create("Xperia Z");
整个流程完全由 DI 容器管理,无需手动 new,解耦更彻底 ✅
6. 原理简析
AutoFactory 的核心是 编译期注解处理(Annotation Processing)。
- 所有
@AutoFactory
注解在编译阶段由AutoFactoryProcessor
解析 - 生成
.java
源文件,参与后续编译 - 不依赖反射,运行时零开销
- 生成代码可见,调试友好
⚠️ 注意:生成的类带有 @Generated
注解,IDE 通常会自动折叠,但可在 target 目录下查看原始源码。
7. 总结
AutoFactory 是一个轻量但实用的工厂代码生成工具,特别适合:
- ✅ 需要频繁创建对象且依赖复杂的场景
- ✅ 与 Guice/Dagger 等 DI 框架协同工作
- ✅ 减少模板代码,提升开发效率
- ✅ 避免手写工厂时的空指针、参数错位等低级错误
结合 AutoValue
使用,能进一步简化不可变对象和工厂的组合模式。
💡 项目地址:GitHub - google/auto