Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Guice:从XML文件设置绑定_Java_Xml_Dependency Injection_Guice_Dynamic Binding - Fatal编程技术网

Java Guice:从XML文件设置绑定

Java Guice:从XML文件设置绑定,java,xml,dependency-injection,guice,dynamic-binding,Java,Xml,Dependency Injection,Guice,Dynamic Binding,我正在尝试使用Guice并在XML文件的帮助下进行所有绑定。在我的模块(比方说“CustomModule”)中,我想加载一个XML文件并对其进行解析以设置所有绑定 我能够加载XML文件并检索所需的所有值(下面是我的XML文件的一个示例),但我无法使用这些值来bind(interfaceValue).to(implementationValue) 到目前为止,我所尝试的: 加载XML文件,检索所有值并将其用作: bind(Class.fromName(Ivalue)).to(Class.fromN

我正在尝试使用Guice并在XML文件的帮助下进行所有绑定。在我的模块(比方说“CustomModule”)中,我想加载一个XML文件并对其进行解析以设置所有绑定

我能够加载XML文件并检索所需的所有值(下面是我的XML文件的一个示例),但我无法使用这些值来
bind(interfaceValue).to(implementationValue)

到目前为止,我所尝试的:

  • 加载XML文件,检索所有值并将其用作:
    bind(Class.fromName(Ivalue)).to(Class.fromName(Value))其中
    Ivalue
    InterfaceFoo
    Value
    Foo
  • 将XML文件作为属性文件加载,并使用
    Names.bindProperties(binder(),Properties)
  • 手动绑定,这不是我想要的
  • 结果:

  • 不起作用,因为Guice无法验证该实现是否是接口的实现
  • 给出错误
    未绑定接口的实现
  • 工作正常,但不需要,因为我必须编辑我的
    CustomModule
    来更改绑定(如果我希望
    Bar
    成为
    interfacefo
    的实现)
  • ,但由于没有太多关于它的文档,因此没有太多的成功。我也在这里寻找解决方案,但大多数时候问题都是关于属性或注释的使用

    是否有一种简单的方法来指定文件中的接口/实现,并将其作为“配置”提供给Guice

    我的XML文件:
    据我对Guice的了解,大多数绑定的一致性检查都是在编译时进行的,所以way#1无法正常工作。我认为您可以尝试使用即时绑定()和/或提供程序(),但最终我认为您无法实现目标。在我看来,最大的限制是您必须在源代码中明确指定要绑定的接口,然后您可以(可能)创建一个提供程序来解析xml并通过Class.forName返回正确的实现。我不知道这是否能满足您的需求,但也许这是一个起点。

    Guice并不是专门为此而设计的。 其思想是,通过在类中执行,您可以获得在类中执行的所有功能和灵活性/
    @提供了
    方法、
    提供程序
    实现、AOP等等。正如你所观察到的,它确实存在,但这并不是你所说的原因所要做的

    但是,如果您愿意使用原始类型,您实际上可以执行方法1,然后自己检查类。这不是最干净的代码,但请注意,您的问题是
    类中的泛型类型,而不是Guice。下面是一个示例,注释掉的伪代码指出了要使此代码在生产中正常工作所需的更改。我想如果你已经走到了这一步,你可以自己解决这个问题。下面是说明该想法的代码:

    import com.google.inject.AbstractModule;
    import com.google.inject.Guice;
    import com.google.inject.Injector;
    
    public class DynamicBinding {
      static final String interfaceExample = "DynamicBinding$Foo";
      static final String implementationExample = "DynamicBinding$FooBar";
    
      public static void main(String... args) throws ClassNotFoundException {
        Injector inj = Guice.createInjector(new CustomModule());
        Foo blue = inj.getInstance(Foo.class);
        blue.doSomething();
      }
    
      static class CustomModule extends AbstractModule {
    
        @Override
        protected void configure() {
          // for (Entry<interface, implementation> : xml file) {
          bindFromStrings(interfaceExample, implementationExample);
          // }
        }
    
        private void bindFromStrings(String interfaceClass, String implClass) {
          try {
            Class fooClass = Class.forName(interfaceClass);
            // I recommend defining a custom exception here with a better message
            if (!fooClass.isInterface()) {
              throw new Exception("fooClass must be an interface!");
            }
    
            Class fooBarClass = Class.forName(implClass);
            // I recommend defining a custom exception here with a better message
            if (!fooClass.isAssignableFrom(fooBarClass)) {
              throw new Exception("classes must be in same inheritance hierarchy");
            }
    
            bind(fooClass).to(fooBarClass);
          } catch (Exception e) {
            // Logger.getLogger().log(blah);
            e.printStackTrace();
          }
        }
      }
    
      public static interface Foo {
        void doSomething();
      }
    
      public static class FooBar implements Foo {
        @Override
        public void doSomething() {
          System.out.println(this.getClass());
        }
      }
    }
    

    我找到了问题的解决方案,正如durron597所说,问题来自泛型
    ,而不是直接来自Guice。我设法让一些东西起作用,但它有它的局限性。以下是注释的代码,以便于理解

    自定义模块类

    @Override
    protected void configure() {
        // for each entry we got in the xml file
        for(Entry<String, String> entry : classNames.entrySet()){
            try {
                // we create the interface-typed class
                Class<IInterface> itf = (Class<IInterface>) Class.forName(entry.getKey());
                // and the implementation-typed class
                Class<IImplementation> concrete = (Class<IImplementation>) Class.forName(entry.getValue());
                // to finally bind them together
                bind(itf).to(concrete);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(GuiceModule.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    

    谢谢你的建议。即时绑定并不适合我的情况,因为这意味着我的接口将只由特定类实现,这是错误的,因为它可以根据choosen配置进行更改。最好的解决方案是只根据提供的XML文件使用动态绑定。我将更深入地了解供应商,谢谢。欢迎来到StackOverflow!我很高兴你决定开始发布问题和答案;这是你第一个写得非常好的问题。坚持下去!旁白:请注意,这是一个专家问答的网站,而不是一个论坛——说“我是初学者”或“这是我的第一个问题”之类的话通常是不受欢迎的,因为它们有损于问题本身,所以我将其删除。好的,谢谢你!在接下来的问题中,我会记住这一点。谢谢你的回答@durron597。的确,它提供了更多的灵活性,
    提供者
    非常有趣,但似乎我们必须“硬编码”我们想要提供的东西。我想要一种库,只需向它传递一个配置文件,库就可以进行神奇的绑定。我找到了另一个解决办法,但我会接受你的,因为它更干净。再次感谢您,如果我对
    提供者
    说错了什么,请告诉我。我已经看过了您所说的
    提供者
    ,您是对的。我现在明白了为什么您要谈论灵活性和功能,它们可以提供大量的实现,所有这些实现都来自一个接口(借助于保存在某处的一些配置)。如果我能让它工作起来,我会发布一个例子,但是你的回答帮助我理解Guice是如何以及为什么如此强大。如果你不像我在回答中那样检查
    是否可从中识别,你就有风险了。试着用不在同一层次结构中的类运行模块,看看会发生什么。你是对的@durron597,我知道你污染堆的意思。另外,我的解决方案有点“危险”:它意味着要完全了解类/接口及其关系。最后,我放弃了这个解决方案,改用Providers/ProvidedBy注释。如果有人仍然在寻找关于“动态guice绑定”的解决方案,我会在这里发布。
    
    public class ServiceProvider {
        // declaration of the services available [FOR NOW]
        @Inject IReaderService iReaderService;
        @Inject IReportService iReportService;
        @Inject ISerializerService iSerializerService;
        @Inject ILoggerService iLoggerService;
    
        public ServiceProvider(){
        }
    
        // getters of the services injected
        public IReaderService getReaderService() {
            return iReaderService;
        }
    
        public IReportService getReportService() {
            return iReportService;
        }
    
        public ISerializerService getSerializerService() {
            return iSerializerService;
        }
    
        public ILoggerService getLoggerService() {
            return iLoggerService;
        }
    }
    
    import com.google.inject.AbstractModule;
    import com.google.inject.Guice;
    import com.google.inject.Injector;
    
    public class DynamicBinding {
      static final String interfaceExample = "DynamicBinding$Foo";
      static final String implementationExample = "DynamicBinding$FooBar";
    
      public static void main(String... args) throws ClassNotFoundException {
        Injector inj = Guice.createInjector(new CustomModule());
        Foo blue = inj.getInstance(Foo.class);
        blue.doSomething();
      }
    
      static class CustomModule extends AbstractModule {
    
        @Override
        protected void configure() {
          // for (Entry<interface, implementation> : xml file) {
          bindFromStrings(interfaceExample, implementationExample);
          // }
        }
    
        private void bindFromStrings(String interfaceClass, String implClass) {
          try {
            Class fooClass = Class.forName(interfaceClass);
            // I recommend defining a custom exception here with a better message
            if (!fooClass.isInterface()) {
              throw new Exception("fooClass must be an interface!");
            }
    
            Class fooBarClass = Class.forName(implClass);
            // I recommend defining a custom exception here with a better message
            if (!fooClass.isAssignableFrom(fooBarClass)) {
              throw new Exception("classes must be in same inheritance hierarchy");
            }
    
            bind(fooClass).to(fooBarClass);
          } catch (Exception e) {
            // Logger.getLogger().log(blah);
            e.printStackTrace();
          }
        }
      }
    
      public static interface Foo {
        void doSomething();
      }
    
      public static class FooBar implements Foo {
        @Override
        public void doSomething() {
          System.out.println(this.getClass());
        }
      }
    }
    
    class DynamicBinding$FooBar
    
    @Override
    protected void configure() {
        // for each entry we got in the xml file
        for(Entry<String, String> entry : classNames.entrySet()){
            try {
                // we create the interface-typed class
                Class<IInterface> itf = (Class<IInterface>) Class.forName(entry.getKey());
                // and the implementation-typed class
                Class<IImplementation> concrete = (Class<IImplementation>) Class.forName(entry.getValue());
                // to finally bind them together
                bind(itf).to(concrete);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(GuiceModule.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    private void parseXmlBindings(){
        try {
            File file = new     File(getClass().getResource("guiceBindings.xml").toURI());
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getElementsByTagName("binding");
    
            for(int i = 0; i < nodeList.getLength(); i++){
                Node node = nodeList.item(i);
                if(node.getNodeType() == Node.ELEMENT_NODE){
                    Element binding = (Element) node;
    
                    NodeList itfList = binding.getElementsByTagName("interface");
                    Element itfElement = (Element) itfList.item(0);
                    NodeList itfValue = itfElement.getChildNodes();
    
                    NodeList concreteList = binding.getElementsByTagName("implementation");
                    Element concreteElement = (Element) concreteList.item(0);
                    NodeList concreteValue = concreteElement.getChildNodes();
    
                    classNames.put(itfValue.item(0).getNodeValue().trim(), concreteValue.item(0).getNodeValue().trim());
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }