Я вижу, что много примеров Java используют внедрение зависимости с частными полями без общедоступного метода set как это:
public SomeClass {
@Inject
private SomeResource resource;
}
Но это - плохая идея, когда инжекция должна быть выполнена вручную, например, в модульных тестах.
Существует несколько возможностей решить это:
setSomeResource(SomeResource r)
Я хотел бы избежать метода set, так как ничего действительно не происходит в нем. Таким образом, я предпочел бы общественность или защищенный пакет. Что Вы рекомендуете?
Я предпочитаю сеттер
Но это только мое мнение
.Добавление сеттеров не является оптимальным решением, так как вы добавляете производственный код, который не нужен.
Альтернативой является использование класса Spring's ReflectionTestUtils для введения тестовых зависимостей с помощью отражения, см. http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html
EDIT (2017): Тем не менее, отражение является еще более худшим решением, чем добавление сеттеров. Причиной такого беспорядка является тот факт, что Spring позволяет вводить значения без сеттеров или конструкторов. Моя текущая позиция заключается в том, чтобы придерживаться любого из них и избегать использования черной магической инжекции.
.Я рекомендую использовать сеттер. В этот вопрос касается преимуществ использования геттеров и сеттеров.
.Одним из способов избежать создания сеттера для поля является использование инжекции конструктора. Это даже позволяет объявить поле окончательным.
Все идет так:
public class SomeClass {
private final SomeResource resource;
@Inject
public SomeClass(SomeResource resource) {
this.resource = resource;
}
}
С помощью ответа на мой (связанный с этим) вопрос:
Как серверы приложений вводят в частную полей?
Я написал этот простой пример того, как вводить без сеттеров. Возможно, это поможет
//......................................................
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