Введите в частный, пакет или общедоступное поле или обеспечьте метод set?

Я вижу, что много примеров Java используют внедрение зависимости с частными полями без общедоступного метода set как это:

public SomeClass {
  @Inject
  private SomeResource resource;
}

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

Существует несколько возможностей решить это:

  • добавьте общедоступный метод set: setSomeResource(SomeResource r)
  • обнародуйте поле
  • сделайте полевой пакет защищенным

Я хотел бы избежать метода set, так как ничего действительно не происходит в нем. Таким образом, я предпочел бы общественность или защищенный пакет. Что Вы рекомендуете?

15
задан deamon 7 January 2010 в 16:08
поделиться

5 ответов

Я предпочитаю сеттер

  • легче отлаживать (ставить точку останова в сеттере, а не на доступ/модификацию поля)
  • легче регистрировать
  • легче добавлять некоторую валидацию (хотя это не всегда лучшее место)
  • легче поддерживать двунаправленную поддержку (хотя контейнер МОК может позаботиться об этом)
  • любая другая цель "ручной ООП"

Но это только мое мнение

.
7
ответ дан 1 December 2019 в 01:17
поделиться

Добавление сеттеров не является оптимальным решением, так как вы добавляете производственный код, который не нужен.

Альтернативой является использование класса Spring's ReflectionTestUtils для введения тестовых зависимостей с помощью отражения, см. http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html

EDIT (2017): Тем не менее, отражение является еще более худшим решением, чем добавление сеттеров. Причиной такого беспорядка является тот факт, что Spring позволяет вводить значения без сеттеров или конструкторов. Моя текущая позиция заключается в том, чтобы придерживаться любого из них и избегать использования черной магической инжекции.

.
8
ответ дан 1 December 2019 в 01:17
поделиться

Я рекомендую использовать сеттер. В этот вопрос касается преимуществ использования геттеров и сеттеров.

.
4
ответ дан 1 December 2019 в 01:17
поделиться

Одним из способов избежать создания сеттера для поля является использование инжекции конструктора. Это даже позволяет объявить поле окончательным.

Все идет так:

public class SomeClass {
    private final SomeResource resource;

    @Inject
    public SomeClass(SomeResource resource) {
        this.resource = resource;
    }
}
15
ответ дан 1 December 2019 в 01:17
поделиться

С помощью ответа на мой (связанный с этим) вопрос:

Как серверы приложений вводят в частную полей?

Я написал этот простой пример того, как вводить без сеттеров. Возможно, это поможет

//......................................................
import java.lang.annotation.*;
import java.lang.reflect.*;

//......................................................
@Target(value = {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface Inject {
}

//......................................................
class MyClass {

    @Inject
    private int theValue = 0;

    public int getTheValue() {
        return theValue;
    }
} // class

//......................................................
public class Example {

    //......................................................
    private static void doTheInjection(MyClass u, int value) throws IllegalAccessException {

        Field[] camps = u.getClass().getDeclaredFields();

        System.out.println("------- fields : --------");
        for (Field f : camps) {
            System.out.println(" -> " + f.toString());
            Annotation an = f.getAnnotation(Inject.class);
            if (an != null) {
                System.out.println("       found annotation: " + an.toString());
                System.out.println("       injecting !");
                f.setAccessible(true);
                f.set(u, value);
                f.setAccessible(false);
            }
        }

    } // ()

    //......................................................
    public static void main(String[] args) throws Exception {

        MyClass u = new MyClass();

        doTheInjection(u, 23);

        System.out.println(u.getTheValue());

    } // main ()
} // class

Выполнить вывод:

------- fields : --------
 -> private int MyClass.theValue
       found annotation: @Inject()
       injecting !
23
3
ответ дан 1 December 2019 в 01:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: