2016-09-15 3 views
3

Пожалуйста, объясните правильный способ автоматической проводки с помощью Google-Guice в следующем сценарии, где используется фабрика. Я использую фабрику XML для обработки XSLT.Google Guice Autowiring for Factory

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, который будет продолжать получать запросы и обрабатывать it.But то он должен назвать newTransformer() за каждый полученный запрос.

+0

вам нужен новый трансформатор каждый раз, или вы хотите трансформатор быть доступны через Guice как синглтон в вашем приложении ли? – pandaadb

+0

Мне это нужно как singleton. Я могу использовать один и тот же экземпляр для всех запросов –

ответ

1

Способ сделать это - просто позволить 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)); 
     } 
    } 

Этот класс действует как поставщик вашего трансформатора. Он инициирует его в первый раз, когда требуется, и сохранит экземпляр для вас. В качестве альтернативы вы также можете построить его в конструкторе.

Я впрыскиваю 2 общие свойства (uri resolver и местоположение xslt). Последнее, по крайней мере, может облегчить тестирование вашего приложения (просто введите другой xslt в провайдер, чтобы проверить его?).

Тогда мне нужно, чтобы связать его в любом модуле, так что Guice знает об этом и могу использовать его:

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

Я связывание типа поставщика в одноточечном. Это означает, что в вашем приложении будет использоваться только один экземпляр этого провайдера.

В качестве альтернативы вы можете сделать что-либо из этих 2-х вариантов, а также:

  1. Bind трансформатора в модуле. По существу, весь код создания в модуль в виде, а затем привязать созданный трансформатор как singleton.

  2. Создать метод поставщика. Это просто аннотированный метод в Guice Module, который вернет вам Transformer.

Все они по существу решают одну и ту же проблему: Имейте экземпляр XMLTransformer, готового в приложении для инъекций.

Я надеюсь, что это то, что вы ищете,

Артур

+0

Извините за поздний ответ .. Это сработало хорошо ..Что делать, если мне нужно более одного экземпляра трансформатора с разными значениями для uriresolver и xslt. –

+0

В этом случае вы должны использовать вспомогательную инъекцию и предоставить свое местоположение и преобразователь на заводе перед созданием. Затем вы можете кэшировать свои трансформаторы на основе этих значений, чтобы вам не приходилось создавать их снова и снова. Вы можете прочитать об ассистированных здесь: https://github.com/google/guice/wiki/AssistedInject – pandaadb

Смежные вопросы