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