应用服务器如何注入私有字段?

我看到了这个问题

注入私人,包装或公共领域或提供制定者?

关于如何手动注入带注释的私有字段(方式是添加setter或通过构造函数)

但是,重点是应用程序服务器(如glassfish,axis2,jboss,…)如何能够注入最终的私有字段(不向用户类添加setter或构造函数)?

引用引用的问题:

public SomeClass { @Inject private SomeResource resource; } 

他们是否使用允许访问私有字段的自定义JVM(不是标准的JVM)?

谢谢

这是一个简单的反思“技巧”。 它依赖于Field.setAccessible()方法来强制以编程方式访问成员:

将此对象的可访问标志设置为指示的布尔值。 值true表示reflection对象在使用时应禁止Java语言访问检查。 值false表示reflection对象应强制执行Java语言访问检查。

Reflection API用于获取字段的句柄,调用setAccessible() ,然后可以通过注入框架设置它。

在这里查看示例。

没有魔法,没有自定义VM。

在skaffman的帮助下,我编写了一个关于如何在没有setter的情况下进行注入的简单示例。 也许它有所帮助(它对我有用)

 //...................................................... 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 

值得注意的是,一些框架通过自定义类加载器利用字节码工程来实现相同的结果,而无需reflection成本(reflection可能相当昂贵)