java - 不带 OUT 注解的 Guice 构造函数注入(inject)?

标签 java dependency-injection guice

有人可以帮助实现不带 OUT 注释的 Guice 吗?

public interface IAnimal {
  void makeNoise();
}


public interface IVehicle {
  int getWheelCount();
}





import org.apache.commons.logging.Log;
public class Car implements IVehicle {

    private Log Logger;

    public Car(Log lgr) {
        this.Logger = lgr;
    }

    public final int getWheelCount() {
      this.Logger.info("getWheelCount is returning 4");
      return 4;
    }
}




import org.apache.commons.logging.Log;
public class Dog implements IAnimal {

    private Log Logger;

    public Dog(Log lgr) {
        this.Logger = lgr;
    }

    public final void makeNoise() {
        this.Logger.info("Bark Bark Bark");
    }
}

pom.xml

    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.3</version>
    </dependency>

    <dependency>
        <groupId>com.google.inject</groupId>
        <artifactId>guice</artifactId>
        <version>4.2.0</version>
    </dependency>

我尝试过的:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.google.inject.*;

public class App {

  public static void main(String[] args) {


    Log localLogger = 
        LogFactory.getLog(App.class);

    Injector injector = Guice.createInjector();

    IVehicle veh = injector.getInstance(Car.class);  
    int wc = veh.getWheelCount();

    IAnimal amh = injector.getInstance(Dog.class);  
    amh.makeNoise();
  }
}

我得到的错误是:

Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.

我理解错误。

但我希望我可以将 Guice“指向”正确的构造函数......而不是使用注释。

如您所见,使用默认/空构造函数不是一个好的选择,因为这个示例很简单,但我想坚持使用基于构造函数的注入(inject)。

追加:

根据我在评论中从 Hemant Singh 那里得到的“提示”,我想我更接近了。

我创建了一个 ProductionInjectModule,它使用

bind(MyInterface.class).toConstructor(MyConcrete.class.getConstructor(org.apache.commons.logging.Log.class));

但即使我通过指向特定的构造函数(使用“toConstructor”)来“强制”解决这个问题......我仍然得到:

Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.

啊啊啊啊啊啊啊啊啊!

下面是完整的“模块”代码:

public class App {

  public static void main(String[] args) {
    runGuice();

  }

  private static void runGuice() {
    Log localLogger = LogFactory.getLog(App.class);

    ProductionInjectModule pm = new ProductionInjectModule(localLogger);
    Injector injector = Guice.createInjector(pm);
    ////Injector injector = Guice.createInjector();
    //// injector.injectMembers(localLogger);

    IVehicle veh = injector.getInstance(Car.class);
    int wc = veh.getWheelCount();

    IAnimal amh = injector.getInstance(Dog.class);
    amh.makeNoise();
  }

 }




import com.google.inject.AbstractModule;
import com.google.inject.Module;

public class ProductionInjectModule extends AbstractModule implements Module {
  // public void configure(Binder binder) {
  // binder.bind(IVehicle.class).to(Car.class);
  //// binder.bind(InterfaceB.class).to(ConcreteB.class);
  //// binder.bind(InterfaceC.class).to(ConcreteC.class);
  // }

  private final org.apache.commons.logging.Log Logger;

  public ProductionInjectModule(org.apache.commons.logging.Log concreteLogger) {
    this.Logger = concreteLogger;
  }

  @Override
  protected void configure() {
    try {
      bind(org.apache.commons.logging.Log.class).toInstance(this.Logger);
      bind(IVehicle.class).toConstructor(Car.class.getConstructor(org.apache.commons.logging.Log.class));
      bind(IAnimal.class).toConstructor(Dog.class.getConstructor(org.apache.commons.logging.Log.class));
    } catch (NoSuchMethodException e) {
      addError(e);
    }
  }

}

按照相同的提示,我找到了一些文档来支持:

来自:http://www.baeldung.com/guice

You can also inject a dependency that doesn’t have a default no-arg constructor using constructor binding:

>     public class BasicModule extends AbstractModule {
>   
>     @Override
>     protected void configure() {
>         bind(Boolean.class).toInstance(true);
>         bind(Communication.class).toConstructor(
>           Communication.class.getConstructor(Boolean.TYPE)); } 
The snippet above will inject an instance of Communication using the

constructor that takes a boolean argument. We supply the true argument to the constructor by defining an untargeted binding of the Boolean class.

This untargeted binding will be eagerly supplied to any constructor in the binding that accepts a boolean parameter. With this approach, all dependencies of Communication are injected.

Another approach to constructor-specific binding is the instance binding, where we provide an instance directly in the binding:

>     public class BasicModule extends AbstractModule {
>   
>     @Override
>     protected void configure() {
>         bind(Communication.class)
>           .toInstance(new Communication(true));
>     }     }

2019 年夏季附录:

使用“slf4j”而不是“org.apache.commons”会更明智

org.slf4j.Logger 
and
org.slf4j.LoggerFactory.getLogger(MyClass.class);

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.25</version>
</dependency>

为什么?

https://www.slf4j.org/codes.html#multiple_bindings

Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api. When a library declares a compile-time dependency on a SLF4J binding, it imposes that binding on the end-user, thus negating SLF4J's purpose. When you come across an embedded component declaring a compile-time dependency on any SLF4J binding, please take the time to contact the authors of said component/library and kindly ask them to mend their ways.

最佳答案

我明白了!我在原始问题中的“附加:”区域很接近!但现在我看到了我的小错误。

我上面的 ProductionInjectModule 是正确的。

我的“要求解决”是错误的。

请注意,在我的 getInstance 中,我还有具体内容。

我需要这个:(强调 getInstance 的参数)

IVehicle veh = injector.getInstance(IVehicle.class);
int wc = veh.getWheelCount();

IAnimal amh = injector.getInstance(IAnimal.class);
amh.makeNoise();

完整的工作代码:(带有上面的接口(interface)和具体内容)

public class App {

  public static void main(String[] args) {
    runGuice();

  }

  private static void runGuice() {
    Log localLogger = LogFactory.getLog(App.class);

    ProductionInjectModule pm = new ProductionInjectModule(localLogger);
    Injector injector = Guice.createInjector(pm);

    IVehicle veh = injector.getInstance(IVehicle.class);
    int wc = veh.getWheelCount();

    IAnimal amh = injector.getInstance(IAnimal.class);
    amh.makeNoise();
  }

 }




import com.google.inject.AbstractModule;
import com.google.inject.Module;

public class ProductionInjectModule extends AbstractModule implements Module {

  private final org.apache.commons.logging.Log Logger;

  public ProductionInjectModule(org.apache.commons.logging.Log concreteLogger) {
    this.Logger = concreteLogger;
  }

  @Override
  protected void configure() {
    try {
      bind(org.apache.commons.logging.Log.class).toInstance(this.Logger);
      bind(IVehicle.class).toConstructor(Car.class.getConstructor(org.apache.commons.logging.Log.class));
      bind(IAnimal.class).toConstructor(Dog.class.getConstructor(org.apache.commons.logging.Log.class));
    } catch (NoSuchMethodException e) {
      addError(e);
    }
  }

}

2019 年夏季附录:

使用“slf4j”而不是“org.apache.commons”会更明智

org.slf4j.Logger 
and
org.slf4j.LoggerFactory.getLogger(MyClass.class);

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.25</version>
</dependency>

当然,检查最近的更新:

https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.slf4j%22%20AND%20a%3A%22slf4j-api%22

为什么?

https://www.slf4j.org/codes.html#multiple_bindings

Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api. When a library declares a compile-time dependency on a SLF4J binding, it imposes that binding on the end-user, thus negating SLF4J's purpose. When you come across an embedded component declaring a compile-time dependency on any SLF4J binding, please take the time to contact the authors of said component/library and kindly ask them to mend their ways.

关于java - 不带 OUT 注解的 Guice 构造函数注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50846677/

相关文章:

java - 如何将依赖项注入(inject) Jackson 自定义反序列化器

java - 在 Google Guice 中使用参数执行函数

java - 覆盖 Guice 中的绑定(bind)

java - 关闭 ResultSet 但不关闭 PreparedStatement

java - 我是编程的新手,需要一些帮助和建议

java - LWJGL - 当我的玩家与多个墙壁物体碰撞时,他开始来回弹跳

design-patterns - 注册表模式 Vs 服务定位器模式 Vs 依赖注入(inject)容器

java - Spring@PostConstruct如何初始化final变量?

mvvm - ShellViewModel Caliburn.Micro 中的 ViewModels 引用

java - Spring WebFlux测试抛出 "IllegalStateException: Failed to load ApplicationContext"异常