当前位置: 首页 > 知识库问答 >
问题:

没有注释的Guice构造函数注入?

相威
2023-03-14

有人能帮助实现没有注释的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到正确的构造函数......而不是使用注释。

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

附加:

根据我在评论中从赫曼特·辛格那里得到的“暗示”,我想我离得更近了。

我创建了一个ProductionInjectModule,它使用

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

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

类必须有一个(并且只有一个)用@Inject注释的构造函数或一个非私有的零参数构造函数。

嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎嘎!

完整的“模块”代码如下:

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

还可以使用构造函数绑定注入没有默认无参数构造函数的依赖项:

>     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

接受布尔参数的构造函数。我们通过定义布尔类的非目标绑定,为构造函数提供true参数。

这种无目标的绑定将急切地提供给绑定中接受布尔参数的任何构造函数。通过这种方法,所有通信的依赖性都被注入。

构造函数特定绑定的另一种方法是实例绑定,我们直接在绑定中提供实例:

>     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

库或框架等嵌入式组件不应声明对任何SLF4J绑定的依赖,而应仅依赖于SLF4J api。当库声明对SLF4J绑定的编译时依赖关系时,它会将该绑定强加给最终用户,从而否定了SLF4J的用途。当您遇到一个嵌入式组件声明对任何SLF4J绑定的编译时依赖性时,请花时间联系所述组件/库的作者,并恳请他们改进方法。

共有1个答案

倪德业
2023-03-14

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

我上面的ProductionInjectModule是正确的。

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

注意,在我的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|gav|1|g:"org.slf4j"和a:"slf4j-api"

为什么?

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

库或框架等嵌入式组件不应声明对任何SLF4J绑定的依赖,而应仅依赖于SLF4J api。当库声明对SLF4J绑定的编译时依赖关系时,它会将该绑定强加给最终用户,从而否定了SLF4J的用途。当您遇到一个嵌入式组件声明对任何SLF4J绑定的编译时依赖性时,请花时间联系所述组件/库的作者,并恳请他们改进方法。

 类似资料:
  • 我试图了解DI在我们的代码库(Kotlin)中是如何使用的。我们正在使用googleguice进行依赖注入。 下面是一个示例类: 在模块类中: DepB类别: 据我所知,对于用< code>@Inject注释的变量,Google Guice会使用模块类来解决这些依赖关系。所以< code>DepA对象的注入方式是有意义的。 但是呢?我们如何能够在不指定任何位置的情况下注入DepB?

  • 问题内容: 假设我有一些类似以下的课程。(为简单起见,这是一个虚构类。) 由于我使用不同的实现,并且可能想对该发送功能进行单元测试,因此我认为我应该注入in 的方法。但是我该怎么做呢? 我见过的所有我理解的Guice示例似乎都是在构造函数中进行注入的: 但是我的类在其构造函数中接受了一个参数,我不想注入该参数。那我该怎么办呢? (注意:我是一个完整的Google Guice noob。我认为我了解

  • 我正在使用spring官方教程中的示例进行实验,并且对此代码有一个依赖关系: https://github.com/spring-guides/gs-async-method/tree/master/complete 如果您查看类上的代码,我有两个问题: 当服务器启动时,如果我在这个类的构造函数中放置一个断点,就像在构造函数中一样,是由spring使用配置的bean提供的。但是,构造函数上没有注释

  • 问题内容: 我试图保留JAXB生成的对象。这是示例结构: 下面是类的结构: 现在,该类具有一个参数构造函数,它接受一个String。我想将该字符串作为整个记录的一部分保留在数据库中。我看到了 org.hibernate.InstantiationException:实体的默认构造函数:RecipientDetailsList 尝试保存对象时发生异常。我有两个问题: 我们是否有任何例外处理方法?我无

  • 我有一个类,我需要注入一个变量,但构造函数没有注入guice。 x的值未被注入。guice是否有必要在构造函数中使用注入来识别方法注入?我是否需要从其他类调用此方法才能工作?Thanx提前

  • 我有一个有两个构造函数的类。我正在尝试使用 guice 工厂创建此类的实例。如果未传递任何参数,则应调用默认构造函数。如果传递了参数,则应调用带参数的构造函数。但目前即使我将参数传递给工厂方法,仍然会调用默认构造函数。带参数的构造函数根本不被调用。下面是我的工厂类。 以下是我尝试注入的构造函数。 下面是我在抽象模块实现类中的模块绑定。 下面是我如何调用构造函数。 我在这里做错了什么?任何帮助都将不