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

如何在Java Guice中处理带自身依赖的可注入类

问题根源

  1. ClassA构造器参数未标记@Assisted:ClassA的int number没有用@Assisted注解,Guice无法区分这个参数是工厂传入的动态值还是自身绑定的常量,导致参数传递混乱。
  2. 手动实例与自动注入冲突:你手动创建了ClassB和ClassA实例,但ClassC构造器中的ClassA是Guice自动注入的新实例,而非你手动创建的对象,最终导致所有动态参数被错误复用。

正确整合方案

根据你的使用场景,需要明确:动态参数用@Assisted标记,外部手动创建的依赖通过工厂方法传递,而非依赖Guice自动注入。

步骤1:修正类的注解与构造器

  • ClassA:给int number和ClassB都添加@Assisted,明确二者均为外部传入
public class ClassA {
    private final int number;
    private final ClassB classB;

    @Inject
    public ClassA(@Assisted int number, @Assisted ClassB classB) {
        this.number = number;
        this.classB = classB;
    }

    public String message() {
        return "ClassA number: " + number + ", ClassB number: " + classB.getNumber();
    }
}
  • ClassB:保持原有@Assisted注解不变
@Getter
public class ClassB {
    private final int number;

    @Inject
    public ClassB(@Assisted int number) {
        this.number = number;
    }
}
  • ClassC:给ClassA添加@Assisted,明确该实例由外部传入
public class ClassC {
    final private int number;
    final private ClassA classA;

    @Inject
    public ClassC(@Assisted int number, @Assisted ClassA classA) {
        this.number = number;
        this.classA = classA;
    }

    public String message() {
        String message = classA.message();
        return message + ", ClassC number: " + number;
    }
}

步骤2:修正工厂接口

工厂方法参数需与构造器中@Assisted标记的参数一一对应:

// ClassAFactory
public interface ClassAFactory {
    ClassA create(int number, ClassB classB);
}

// ClassBFactory
public interface ClassBFactory {
    ClassB create(int number);
}

// ClassCFactory
public interface ClassCFactory {
    ClassC create(int number, ClassA classA);
}

步骤3:修正使用代码

通过工厂传递手动创建的实例,避免Guice自动生成新对象:

Injector injector = Guice.createInjector(new AppModule());

// 创建ClassB实例
ClassBFactory bFactory = injector.getInstance(ClassBFactory.class);
ClassB b = bFactory.create(2);

// 传入ClassB实例创建ClassA
ClassAFactory aFactory = injector.getInstance(ClassAFactory.class);
ClassA a = aFactory.create(1, b);

// 传入ClassA实例创建ClassC
ClassCFactory cFactory = injector.getInstance(ClassCFactory.class);
ClassC c = cFactory.create(3, a);

System.out.println(c.message());

此时输出结果为:ClassA number: 1, ClassB number: 2, ClassC number: 3,符合预期。

用Provider替代工厂的示例

Guice的Provider适合自定义实例初始化逻辑,结合AssistedInject可处理动态参数场景。

示例:用Provider创建ClassA

  1. 定义ClassA的Provider:
public class ClassAProvider implements Provider<ClassA> {
    private final int number;
    private final ClassB classB;

    // 动态参数用@Assisted标记,固定依赖由Guice注入
    @Inject
    public ClassAProvider(@Assisted int number, ClassB classB) {
        this.number = number;
        this.classB = classB;
    }

    @Override
    public ClassA get() {
        // 可在此添加自定义初始化逻辑(如参数校验、额外配置)
        return new ClassA(number, classB);
    }
}
  1. 定义Provider的工厂接口:
public interface ClassAProviderFactory {
    ClassAProvider create(int number);
}
  1. 在模块中配置:
install(new FactoryModuleBuilder().build(ClassAProviderFactory.class));
// 绑定固定参数的ClassB实例
bind(ClassB.class).toInstance(new ClassB(2));
  1. 使用方式:
Injector injector = Guice.createInjector(new AppModule());
ClassAProviderFactory providerFactory = injector.getInstance(ClassAProviderFactory.class);
ClassAProvider provider = providerFactory.create(1);
ClassA a = provider.get();

注意:如果所有依赖都是动态参数,直接使用AssistedInject工厂更简洁;Provider更适合需要复用初始化逻辑、或部分依赖为Guice绑定常量的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 15:43:20