2016-09-15 57 views
3

请解释在使用工厂的以下场景中使用Google-Guice自动连线的正确方法。我正在使用XML工厂进行XSLT处理。Google Guice为工厂自动装配

StringWriter strWriter = new StringWriter(); 
System.setProperty("javax.xml.transform.TransformerFactory", 
       "net.sf.saxon.TransformerFactoryImpl"); 
TransformerFactory xmlTransformerFactory = TransformerFactory.newInstance(); 
CustomUriResolver out = new CustomUriResolver(new HashMap<String, StringWriter>()); 
xmlTransformerFactory.setAttribute("http://saxon.sf.net/feature/outputURIResolver", out); 
Transformer xmlTransfomer = xmlTransformerFactory.newTransformer(new StreamSource("src/main/resources/test.xslt")); 
xmlTransfomer.transform(new StreamSource(new StringReader(xml)), new StreamResult(strWriter)); 
System.out.println(out.getResults().size()); 
for(Map.Entry resultEntry : out.getResults().entrySet()){ 
    System.out.println(resultEntry.getValue()); 
}; 

我应该有自动线变压器厂,这需要定制URI resolver.Also这段代码是API将继续接受请求并处理它。但是那么它必须调用newTransformer的一部分()为它收到的每一个请求。

+0

你需要一个新的变压器每次还是要变压器可用通过吉斯在整个应用程序中的单身? – pandaadb

+0

我需要它作为单身..我可以使用相同的实例所有请求 –

回答

1

做到这一点的方法是让Guice简单地处理你的依赖。你如何创建你的依赖关系取决于你 - guice并不在意(除非你必须使用拦截器,在那里你需要为你创建依赖关系)

对于这种情况,我将使用提供者来注入我的依赖关系。你会想要提取所有的创建逻辑,所以它会被执行一次来存储你的转换器,然后在任何地方注入转换器。我使用提供者的原因是我可以注入更多的依赖关系(你可以做通过注释的方法,提供我相信)相同

见这个例子:

public class TransformerProvider implements Provider<Transformer> { 

     @Inject 
     @Named("output.uri.resolver") 
     String outputUriResolver; 

     @Inject 
     @Named("xslt.location") 
     String xsltLocation; 

     Transformer instance = null; 

     @Override 
     public Transformer get() { 
      if(instance == null) { 
       try { 
        instance = create(); 
       } catch (TransformerConfigurationException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
      return instance; 
     } 

     private Transformer create() throws TransformerConfigurationException { 
      System.setProperty("javax.xml.transform.TransformerFactory", 
          "net.sf.saxon.TransformerFactoryImpl"); 
      TransformerFactory xmlTransformerFactory = TransformerFactory.newInstance(); 
      CustomUriResolver out = new CustomUriResolver(new HashMap<String, StringWriter>()); 
      xmlTransformerFactory.setAttribute(outputUriResolver, out); 
      return xmlTransformerFactory.newTransformer(new StreamSource(xsltLocation)); 
     } 
    } 

这个班充当您的Transformer的提供者。它在第一次需要时启动它并将为您存储实例。或者,你也可以在构造函数中构造它。

我注入了2个常见属性(uri resolver和xslt的位置)。后者至少可能使测试应用程序更容易(只需将不同的xslt注入提供程序来测试它)?

然后,我需要让吉斯知道它给它绑定任何模块中,可以使用它:

Injector i = Guice.createInjector(new AbstractModule() { 
      @Override 
      protected void configure() { 
       bind(Transformer.class).toProvider(TransformerProvider.class).in(Singleton.class); // bind factory 
      } 
     }); 

我在一个单独的类型绑定到其供应商。这意味着在整个应用程序中只会使用该提供程序的一个实例。

或者你可以做任何的那些2个选项,以及:

  1. 绑定你的模块中的变压器。基本上把所有的创建代码放到一个guice模块中,然后把创建的Transformer作为一个单例绑定。

  2. 创建提供者方法。这只是Guice模块中的一个注释方法,它将为您返回一个Transformer。

所有这些都基本上解决了同样的问题:在应用程序中准备好用于注入的XMLTransformer实例。

我希望这是你在找什么,

阿图尔

+0

对不起,迟到的回应..这很好.. ..如果我需要用于uriresolver和xslt位置的不同的变量的多个变量的实例 –

+0

在这种情况下,您将使用辅助注入并在创建之前将您的位置和解析器提供给工厂。然后,您可以根据这些值缓存变压器,因此您不必一遍又一遍地创建它们。你可以在这里阅读辅助注射:https://github.com/google/guice/wiki/AssistedInject – pandaadb