代码之家  ›  专栏  ›  技术社区  ›  granadaCoder

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

  •  1
  • granadaCoder  · 技术社区  · 7 年前

    有人能帮助实现没有注释的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");
        }
    }
    

    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.
    

    我理解这个错误。

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

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

    追加:

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

    我创建了一个productionjectmodule,它使用

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

    但是,即使我通过指向一个特定的构造函数(使用“to constructor”)来“强迫”这个问题……。我仍然得到:

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

    嘎嘎!

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

    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

    您还可以插入一个没有默认no arg的依赖项 使用构造函数绑定的构造函数:

    >     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
    

    接受布尔参数的构造函数。我们提供了真实的论据 通过定义布尔值的非目标绑定到构造函数 班级。

    此非目标绑定将急切地提供给 接受布尔参数的绑定。用这种方法,所有 注入通信的依赖项。

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

    >     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。当A 库声明了对slf4j绑定的编译时依赖,它 将该绑定强加于最终用户,从而否定slf4j的目的。 当遇到声明编译时的嵌入式组件时 依赖任何SLF4J绑定,请花时间联系 上述组件/库的作者,请他们修复 方法。

    1 回复  |  直到 6 年前
        1
  •  3
  •   granadaCoder    6 年前

    我得到了它!我的“附加:”区域在原来的问题是接近!但现在我看到了我的小错误。

    我上面的产品项目模块是正确的。

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

    注意在我的例子中,我仍然有混凝土。

    我需要这个:(强调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

    嵌入组件(如库或框架)不应声明 依赖于任何SLF4J绑定,但仅依赖于SLF4J API。当A 库声明了对slf4j绑定的编译时依赖,它 将该绑定强加于最终用户,从而否定slf4j的目的。 当遇到声明编译时的嵌入式组件时 依赖任何SLF4J绑定,请花时间联系 上述组件/库的作者,请他们修复 方法。

    推荐文章