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