编程语言
首页 > 编程语言> > Java-Guice:从XML文件设置绑定

Java-Guice:从XML文件设置绑定

作者:互联网

我正在尝试使用Guice并借助XML文件进行所有绑定.在我的模块中(假设为“ CustomModule”),我想加载一个XML文件并解析它以设置所有绑定.

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

到目前为止,我已经尝试过:

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

结果:

>不起作用,因为Guice无法验证实现是否为接口的实现.
>给出错误没有绑定接口的实现.
>可以,但是不需要,因为我必须编辑CustomModule来更改绑定(在这种情况下,如果我希望Bar成为InterfaceFoo的实现).

I’ve looked at this,但是没有太多的成功,因为上面没有太多的文档.我也在这里寻求关于SO的解决方案,但是大多数时候,问题都与属性或注释的使用有关.

有没有一种简单的方法可以在文件中指定接口/实现并将其作为“配置”提供给Guice?

我的XML文件:

<bindings>
  <binding>
    <interface>interfaces.IReaderService</interface>
    <implementation>implementation.MemsReaderService</implementation>
  </binding>
  <binding>
    <interface>interfaces.IReportService </interface>
    <implementation>implementation.PdfReportService</implementation>
  </binding>
  <binding>
    <interface>interfaces.ISerializerService </interface>
    <implementation>implementation.JsonSerializerService</implementation>
  </binding>
  <binding>
    <interface>interfaces.ILoggerService </interface>
    <implementation>implementation.LoggerService</implementation>
  </binding>
</bindings>

CustomModule.java:

public class GuiceModule extends AbstractModule{

    private HashMap<String, String> classNames = new HashMap<String, String>();

    public GuiceModule(){
    }

    @Override
    protected void configure() {
        /* === Test 1 [NOK : Module doesn't know if A implements B] */
        for(Entry<String, String> entry : classNames.entrySet()){
            try {
                Class<?> itf = Class.forName(entry.getKey());
                Class<?> concrete = Class.forName(entry.getValue());
                bind(itf).to(concrete);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(GuiceModule.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        /* === Test 2 [NOK : Not bound] */
        try{
            File file = new File(getClass().getResource("guiceBindings.xml").toURI());
            Properties properties = new Properties();
            properties.load(new FileReader(file));
            Names.bindProperties(binder(), properties);
        } catch (Exception ex) {
            Logger.getLogger(GuiceModule.class.getName()).log(Level.SEVERE, null, ex);
        }
        /* === Test 3 [OK : Manual edition] */
        bind(IReaderService.class).to(MemsReaderService.class);
        bind(IReportService.class).to(PdfReportService.class);
        bind(ISerializerService.class).to(JsonSerializerService.class);
        bind(ILoggerService.class).to(LoggerService.class);
    }
}

ServiceProvider.java:

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;
    }
}

解决方法:

Guice并非真的为此设计.

想法是,通过在类中执行此操作,您将获得在类/ @Provides方法,Provider< T>中提供的所有功能和灵活性.实现,AOP等.正如您所观察到的,它确实有Named.bindProperties,但这并不是您出于陈述原因而试图这样做的.

但是,如果您愿意使用原始类型,则实际上可以执行方法1,然后自己检查类.这不是最干净的代码,但是请注意,您的问题是Class<?>中的通用类型,而不是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());
    }
  }
}

输出:

class DynamicBinding$FooBar

标签:dependency-injection,guice,dynamic-binding,xml,java
来源: https://codeday.me/bug/20191028/1951412.html