2009-03-09 2 views
14

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

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

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

ответ

6

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

+1

Этот ответ подразумевает, что «кодирование для интерфейсов» означает, что каждый класс должен реализовывать отдельный интерфейс. Это не то, что означает принцип, описанный в книге GoF. В действительности это применимо только к случаям, когда вам нужно или уже есть два отдельных типа объектов: один для абстракции (интерфейс) и другой для одной реализации этой абстракции. –

+0

Я думаю, что вы, скорее всего, обнаружите, что классы, которые нужно вводить друг в друга в общем приложении Spring, являются ** услугами ** классами, такими как 'Dao' и т. Д. Я обнаружил, что большое количество из них может предположительно имеют альтернативные реализации –

+1

Да, когда у вас есть несколько реализаций, применяется принцип «код для интерфейса, а не реализация». Но говорить такие вещи, как «если вы кодируете интерфейсы ...» без четкого контекста, вводит в заблуждение и легко может быть неправильно интерпретировано менее опытными разработчиками.Чрезмерное использование отдельных интерфейсов вызывает большой вред, ИМО. –

15

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

+2

+1 к инъекции конструктора. Выражает зависимости намного сильнее и устраняет необходимость в «смешных» сеттерах. – flq

+0

constructor injection ++: как только вы создаете объект, он должен быть готов к использованию и в согласованном состоянии. – Kalecser

+2

Не все свойства могут потребоваться для правильной работы класса. В этом случае я всегда добавляю их через сеттеры –

5

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

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

+0

+1 - пропаганда аннотаций, где это возможно, является хорошей вещью. Сейчас я пытаюсь сделать сам прыжок, но трудно разбить эту привычку XML. – duffymo

3

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

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

0

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

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

Мне нужно будет проверить @Autowire, tho '.

TJ

1

Я был в основном один и тот же вопрос здесь:

Encapsulation in the age of frameworks

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

1

Никогда не @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 
    } 
} 
0

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

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

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

public void setAge(int age) { 
if (age < 0) { 
    throw new AppException("invalid age!"); 
} 
this.age=age; 
} 
0

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

позже, Дин