Как серверы приложений внедряются в частные поля?
Я видел этот вопрос
Вложить в личное, пакетное или общедоступное поле или предоставить сеттер?
о том, как вручную вводить в аннотированные частные поля (способ добавления сеттеров
или через конструктор)
Но дело в том, как сервер приложений (например, glassfish, axis2, jboss,...)
может вводить в конечное частное поле (без добавления сеттеров или конструкторов
к классу пользователя)?
Цитируя упомянутый вопрос:
public SomeClass {
@Inject
private SomeResource resource;
}
Используют ли они индивидуальную JVM (не стандартную), которая позволяет получить доступ к закрытым полям?
Спасибо
Ответы
Ответ 1
Это простой "трюк". Он полагается на Field.setAccessible()
, чтобы заставить пользователя быть доступным программно:
Установите для этого доступного флага объект к указанному логическому значению. Значение true указывает, что отраженный объект должен подавлять Java проверка доступа к языку, когда это используемый. Значение false указывает на то, что отраженный объект должен Проверка доступа к языку Java.
API Reflection используется для получения дескриптора в поле, вызывается setAccessible()
, а затем его можно установить с помощью рамки для инъекций.
См. пример здесь.
Никакой магии, никакой пользовательской виртуальной машины.
Ответ 2
С помощью скаффмана я закодировал этот простой пример о том, как вводить без сеттеров.
Возможно, это помогает (мне это удалось)
//......................................................
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
Также стоит отметить, что некоторые фреймворки используют технологию байт-кода через пользовательский загрузчик классов для достижения того же результата без стоимости Reflection (отражение может быть довольно дорогое время от времени)