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


原始标题:Introduction to AutoFactory