Разве Spring инъекция зависимостей не нарушает сокрытие информации? - PullRequest
14 голосов
/ 09 марта 2009

Исходя из C ++, я должен освоить сложность Java мир и его рамки. Глядя на весенние рамки для DI я мне трудно поверить, что я должен заставить каждый сеттер работать который будет предметом для DI общественности. Разве это требование не нарушает принцип сокрытия информации?

Конечно, я хочу, чтобы весна смогла установить некоторые приватные части моего классы, но я, конечно, не хочу, чтобы каждый класс клиента был в состоянии сделать то же самое.

Что мне здесь не хватает?

Ответы [ 10 ]

15 голосов
/ 09 марта 2009

Я согласен с вашей точкой зрения - поэтому я предпочитаю инжектор конструктора.

6 голосов
/ 09 марта 2009

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

5 голосов
/ 09 марта 2009

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

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

3 голосов
/ 09 марта 2009

Если вы используете весенние аннотации (@Autowired), вы можете использовать DI для частных пользователей.

Если вы идете на слабую связь и (единичную) тестируемость, на мой взгляд, пружины DI выделяют информацию, которая не должна быть скрыта.

1 голос
/ 18 июня 2009

Никогда не использовал @Autowired, мне нравится использовать параметры в конструкторах, но иногда трудно понять, что означают параметры, особенно если у вас много параметров - в этом случае я предпочитаю использовать подход "Builder" описано в Эффективной Java. Конструктор получает объект сборки (у которого есть сеттеры) и конструирует себя вместе с ним. Внедренные атрибуты класса являются окончательными (неизменяемость), класс «Builder» содержит установщики, но не получатели (в этом нет необходимости, поскольку мы объявляем его как внутренний класс создаваемого класса), и нет необходимости в установщиках быть созданным только для весны:

<bean id="runnable" class="MyClass">
   <constructor-arg>
     <bean class="MyClass$Builder">
       <property name="p1" value="p1Value"/>
       <property name="p2" value="p2Value"/>
       <property name="p3" value="p3Value"/>
       <property name="p4" value="p4Value"/>
     </bean>
   </constructor-arg>
</bean>

Код класса:

public class MyClass {
   private final String p1;
   private final String p2;
   private final String p3;
   private final String p4;
   public MyClass(Builder builder) {
      this.p1 = builder.p1;
      this.p2 = builder.p2;
      this.p3 = builder.p3;
      this.p4 = builder.p4;
   }

   ...

   public static class Builder {
      private String p1;
      private String p2;
      private String p3;
      private String p4;
      public void setP1(String p1) {
         this.p1 = p1;
      }
      ... and so on
   }
}
1 голос
/ 09 марта 2009

У меня был в основном тот же вопрос:

Инкапсуляция в эпоху каркасов

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

0 голосов
/ 27 апреля 2012

И это еще одна причина, по которой я предпочитаю Guice;) И Guice, и Spring реализуют спецификацию JSR 330 DI, но с помощью Guice я могу вводить в свои частные поля экземпляра без установщиков, мне действительно не нравится инжекция в конструктор, поскольку рефакторинг кажется труднее. По моему скромному мнению, это просто намного больше печатает за небольшую ценность.

позже, Декан

0 голосов
/ 13 апреля 2012

Не согласен с тем, что Spring разрывает инкапсуляцию. Даже если у вас есть pojo, где вы получаете и выставляете на показ в классе, и третья сторона использует ваш jar, все же есть вероятность, что потребитель jar сделает то же самое, что возможно с конфигурацией bean-компонента Spring. (верно для любого другого языка ООП)

Spring просто предоставляет способ, который может быть реализован через код, и этот элемент управления перемещен из кода (IOC).

Потребитель (учтите, что другой программист использует вашу библиотеку), создает bean-компонент с помощью весенней конфигурации, но ваш код все еще имеет контроль. Никакое тело не мешает вам проверять ввод, данный пользователем (Spring IOC Framework также проходит через тот же код, который выполняется другим классом, вызывающим ваш установщик) в установщике.

public void setAge(int age) {
 if ( age < 0 ) {
   throw new AppException("invalid age!");
 }
 this.age=age;
}
0 голосов
/ 18 июня 2009

Просто хотел упомянуть, что я (непреднамеренно) опубликовал более общую версию этого вопроса и что у нее есть некоторые дополнительные идеи по этому вопросу: Должен ли ввод зависимостей осуществляться за счет инкапсуляции?

0 голосов
/ 09 марта 2009

Полагаю, это компромисс. Вы уменьшаете жестко привязанные зависимости, но вы потенциально можете раскрыть внутренности своей реализации. С помощью правильных абстракций вы также можете уменьшить это, но затем вы увеличите сложность базы кода (например, имея общее «Соединение», которое может быть соединением LDAP или соединением SQL).

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

Мне придется проверить @Autowire, tho '.

TJ

...