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