不带 OUT 注解的 Guice 构造函数注入?

Guice Constructor Injection withOUT Annotations?

有人可以帮助实现带有 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.

我理解错误。

但我希望我可以 "point" 指导正确的构造函数......而不是使用注释。

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

追加:

根据评论中来自 Hemant Singh 的 "hint",我想我更接近了。

我创建了一个 ProductionInjectModule,它使用

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

但即使我 "forcing" 通过指向特定构造函数(使用 "toConstructor")来解决问题......我仍然得到:

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

Gaaaaaaaaaaaaaaaaaaaaa!

完整 "module" 代码如下:

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.

我明白了!我在原问题中的 "APPEND:" 区域很接近!但是现在我看到了我的小错误。

我上面的 ProductionInjectModule 是正确的。

我的"ask to resolve"错了。

注意我的getInstance,我还有具体的。

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

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

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

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

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.