java 使用Guice将参数传递给构造函数

cwtwac6a  于 2023-10-14  发布在  Java
关注(0)|答案(6)|浏览(146)

我有一个工厂如下,

public final class Application {

    private static IFoo foo;

    public static IFoo getFoo(String bar)
    {
        // i need to inject bar to the constructor of Foo
        // obvious i have to do something, not sure what
        Injector injector = Guice.createInjector();
        logger = injector.getInstance(Foo.class);
        return logger;              
    }

}

这就是Foo的定义:

class Foo
{
   Foo(String bar)
   {

   }

}

好的,我不知道如何用Guice将这个参数传递给Foo构造函数?
有什么想法吗?

lkaoscv7

lkaoscv71#

所有“Guice构造函数参数”的答案似乎在某种程度上是不完整的。这里是一个完整的解决方案,包括使用和视觉:

interface FooInterface {
    String getFooName();
}

//注解实现类上的构造函数和辅助参数

class Foo implements FooInterface {
    String bar;

    @Inject
    Foo(@Assisted String bar) {
        this.bar = bar;
    }

    // return the final name
    public String getFooName() {
        return this.bar;
    }

}

//使用create()方法创建一个工厂接口,该方法只接受辅助参数。
// FooFactory接口没有显式实现类(Guice Magic)

interface FooFactory {
    Foo create(String bar);
}

//将该工厂绑定到由AssistedInject创建的提供程序

class BinderModule implements Module {

    public void configure(Binder binder) {
        binder.install(new FactoryModuleBuilder()
                .implement(FooInterface.class, Foo.class)
                .build(FooFactory.class));
    }
}

//现在使用它:

class FooAction {
    @Inject private FooFactory fooFactory;

    public String doFoo() {
        // Send bar details through the Factory, not the "injector"
        Foo f = fooFactory.create("This foo is named bar. How lovely!");
        return f.getFooName(); // "This foo is named bar. How lovely!"
    }
}

这里有很多帮助:https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html

velaa5lx

velaa5lx2#

您可能正在寻找的是使用Guice工厂。特别容易与AssistedInject功能,但他们有一个manual example at the top of the page.对于手动示例来说,简单来说就是在非静态getFoo方法下获取工厂,将所需的任何参数传递给该工厂,然后从那里构建对象。
如果在Foo中有方法拦截,这不会直接起作用,但在许多其他情况下它会起作用。
要使用AssistedInject,对我来说,它有更清晰的语义,意味着更少的手动连接,你需要在类路径中使用guice-assistedinject扩展,然后在创建Foo时(好吧,FooImpl,我们应该使用接口):

@Inject
public FooImpl(@Assisted String bar)
{
    this.baz = bar;
}

然后创建一个FooFactory接口:

public interface FooFactory {
    public Foo create(String bar);
}

然后在guice模块中:

install(new FactoryModuleBuilder()
    .implement(Foo.class, FooImpl.class)
    .build(FooFactory.class));

您可以查看javadoc for FactoryModuleBuilder以获得更复杂工厂的示例。

vsaztqbk

vsaztqbk3#

我知道这是一个老问题,但今天我自己也遇到了这个问题。我只需要两个或最多三个不同的'Foo'示例,我真的不想写所有的工厂的bolierplate代码。用谷歌搜索一下,我发现了这个Stubbisms – Tony’s Weblog,我建议这个解决方案,如果你确切地知道你需要什么样的示例,它是完美的。
在Guice模块中:

bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic A");
        }
    });
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic B");
        }
    });

在Java 8中:

bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(() -> new FooImpl("first"));
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(() -> new FooImpl("second"));

在你的服务的构造函数中,你需要Foo示例:

@Inject
public MyService (
    @Named("firstFoo") Foo firstFoo,
    @Named("secondFoo") Foo secondFoo) {
}

Foo在我的案例中:

public class FooImpl implements Foo {

    private String name;

    public FooImpl(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

希望它能帮助某人。

5uzkadbs

5uzkadbs4#

如果这个类是一个工厂,它应该是一个Guice管理的对象,有一个非静态的getFoo方法,getFoo方法只使用

new Foo(bar)

不是每个类都需要由Guice示例化。
另请参阅AssistedInject,以避免自己创建这个工厂,让Guice为您创建一个。

t8e9dugd

t8e9dugd5#

虽然这不是一个直接回答你的问题,希望它有帮助。我试图理解构造函数参数在哪里传递。如果它们是自定义类,它们应该绑定在模块中。

Class CustomHandler {

  private Config config;

  @Inject
  CustomHandler(Config config) {
    this.config = config;
  }

  public void handle() {
    // handle using config here
  }
}

约束力:

class Module extends AbstractModule {
  bind(Handler.class).to(CustomHandler.class);
  bind(Config.class).to(CustomConfig.class);
}

注射:

CustomHandler handler = injector.getInstance(CustomHandler.class);
handler.handle();
2wnc66cl

2wnc66cl6#

这就是我们最终做的。这是一个糟糕的解决方案,只应该在你没有时间的时候使用,只想活着看到另一天。
1.删除所有构造函数,使类成为可缺省构造的。
1.添加一个名为init或类似的公共方法,该方法将依赖项作为参数并将其分配给字段。
1.使用Guice的Injector.getInstance()为您进行类发现和构造,然后使用您实际需要的字段调用init方法。
通过执行一些积极的空值检查(通过抛出适当格式的IllegalStateException来通知不经意的调用方需要调用init),可以在一定程度上原谅这样做。

相关问题