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

时间:2010-04-05 15:40:01

标签: java dependency-injection annotations

我看到了这个问题

Inject into private, package or public field or provide a setter?

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

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

引用引用的问题:

public SomeClass {
  @Inject
  private SomeResource resource;
}

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

由于

3 个答案:

答案 0 :(得分:16)

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

  

为此设置可访问标志   对象指示的布尔值。   值为true表示该值   反射对象应该压制Java   语言访问检查的时间   用过的。值false表示   反射对象应该强制执行   Java语言访问检查。

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

查看示例here

没有魔法,没有自定义虚拟机。

答案 1 :(得分:6)

在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

答案 2 :(得分:3)

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