2016-08-27 8 views
0

КонтекстВесна - Инъекция бобов с использованием Builder шаблон

Приложение, которое использует Spring 4.1.7. Все конфигурации хранятся в файлах XML (не используя аннотации), и я предпочитаю сохранять их таким образом (но я могу изменить способы, как это делается, если я должен).

Проблема

Я создал новый класс, который поставляется с классом строителя.

Теперь я хотел бы добавить другие компоненты в этот новый класс. Я могу, вероятно, использовать методы поиска и аналогичные решения для этого, а затем использовать конструктор нового класса в компонентах вызывающего объекта для создания экземпляра. Тем не менее, я скорее экземпляр этого нового класса, который должен быть добавлен к его компонентам-вызывающим, затем они создают один через строителя. Вот где я не уверен, как я могу это сделать. Например, для меня это выглядит как абстрактная фабрика, но я не знаю, как передать эти параметры (которые передаются разработчику) во время выполнения на абстрактную фабрику, а затем заводы, которые она создает.

Некоторые фрагменты кода, чтобы сделать вопрос яснее:

public final class Processor { 

    private final StatusEnum newStatus; 
    private final Long timeOut; 

    // I'd like this to be be injected by Spring through its setter (below) 
    private DaoBean daoInstance; 

    private Processor() { 
     this.newStatus = null; 
     this.timeOut = null; 
    } 

    private Processor(Builder builder) { 
     this.newStatus = builder.getNewStatus(); 
     this.timeOut = builder.getTimeOut(); 
    } 

    // To be called by Spring 
    public void setDaoInstance(DaoBean instance) { 
     this.daoInstance = instance; 
    } 

    public void updateDatabase() { 
     daoInstance.update(newStatus, timeOut); 
    } 

    // Builder class 
    public static final class Builder { 
     private StatusEnum newStatus; 
     private Long timeOut; 
     // lots of other fields 

     public Long getTimeOut() { 
      return this.timeOut; 
     } 

     public StatusEnum getNewStatus() { 
      return this.newStatus; 
     } 

     public Builder withTimeOut(Long timeOut) { 
      this.timeOut = timeOut; 
      return this; 
     } 

     public Builder withNewStatus(StatusEnum newStatus) { 
      this.newStatus = newStatus; 
      return this; 
     } 

     public Processor build() { 
      return new Processor(this); 
     } 
    } 
} 

Я хотел бы экземпляр «DaoBean», который будет введен в класс «Processor». Но для этого процессор должен быть bean или иначе я должен использовать что-то вроде lookup-методов. С другой стороны, там, где я хочу использовать процессор, я должен сделать что-то вроде этого:

new Processor.Builder() 
    .withTimeOut(1000L) 
    .withNewStatus(StatusEnum.UPDATED) 
    .build() 
    .updateDatabase(); 

Вместо этого, я задаюсь вопросом, могу ли я сделать процессор боба, что весна может придать своим абонентам при сохранении его неизменность. Затем экземпляр DaoBean может быть введен в процессор по весне. Таким образом, я смогу выделить код проводки и бизнес-логику.

Следует отметить, что Builder имеет намного больше, чем 2 поля, и не все они должны быть установлены. Вот почему я думал, что абстрактная фабрика - это путь (создание экземпляров Процессора по-разному).

+0

Извините, я еще не понял, какова ваша фактическая проблема. Не могли бы вы разместить какой-нибудь код? Например, этот класс? Таким образом, мы лучше поймем, что у вас есть и что вы хотите ... –

+0

Обновлен вопрос. –

ответ

0

Одно из решений, сохраняя при этом строитель, вероятно, будет просто сделать сам родника боб строитель ...

Это позволяет что-то вроде этого ..

@Autowired 
private Builder builder; 

public void someMethod() { 
    Result = builder.withX(...).doSomething(); 
} 

Таким образом, ваш результат объект неизменен, может быть создан с помощью красивого строителя, и строитель может ввести в него Spring-компонент (dao, в вашем случае), даже не заметив, что он есть.

И единственное, что меняется в том, что вы не создаете строителю себя, но пусть весна создать его для вас ...

@Component 
@Scope("prototype") // normally a good idea 
public static class Builder { 
    @Autowired 
    private DaoBean dao; 

    // your logic here 
} 

(Одинаковые работы с JavaConfig или XML-конфигурации, если вы не хотят сканировать.)

Специально со многими комбинациями я предпочитаю шаблон строителя, поскольку фабрике нужны сложные сигнатуры методов. Конечно, у строителя есть недостаток, который вы не можете проверить во время компиляции, если данная комбинация типов атрибутов по крайней мере теоретически приемлема. Хорошо, вы могли бы имитировать это с различными строителями, но это, вероятно, было бы излишним.

+0

Спасибо. Что бы вы предложили мне сделать с зависимостями процессора (например, DaoBean)? Кроме того, я не совсем понял, что вы подразумеваете под «у строителя есть недостаток». Обычно я проверяю параметры в функции построения. –

+0

. Зависимости процессора, например. DaoBean, вводится в Builder к весне, а затем передается процессору разработчиком. (Я склонен создавать (потенциально закрытый) конструктор, который берет сам Builder, тем самым устраняя необходимость в сложных конструкторских подписях или скрытых методах настройки). И я просто заметил, что у вас нет шансов сказать кому-нибудь «У вас есть выбор String, String, int или String, int или просто int» только с сигнатурами (во время компиляции), поэтому все проверки должны выполняться во время выполнения (но это очень незначительный недостаток в TDD). –

+0

Спасибо. Это будет сделано. –