Java:使用反射注入字段的最快方法是什么?

时间:2009-10-28 12:08:13

标签: java reflection annotations code-injection pojo

假设我有很多类,它们是使用Java反射构建的(出于某种原因)。现在我需要将值后注入到字段中 用@PostInject注释。

public class SomeClass {
  @PostInject
  private final String someString = null;

  public void someMethod() {
    // here, someString has a value.
  }
}

我的问题是:使用反射设置字段的快捷方式是什么?
记住,我需要经常在很多课程上这样做,那就是 为什么表现是相关的。

这个伪代码显示了我通过直觉做的事情:

  • 获取班级的所有领域 clazz.getFields();
  • 检查,用@PostInject注释 eachField.getAnnotation(PostInject.class);
  • 使这些字段可访问
    eachAnnotatedField.setAccessible(true);
  • 将它们设置为某个值
    eachAnnotatedField.set(clazz, someValue);

我害怕获得所有领域是最慢的事情 当我从一开始就知道它时,我可以找到一个领域吗?

注意:我不能让这些类实现一些接口,这会 允许使用方法设置字段。我需要 POJOs。

注意2:为什么我要进行现场注入:从API用户的角度来看,必须能够使用最终字段。此外,当API先验地不知道字段的类型和数量时,不可能使用接口实现字段初始化。

注意事项2b:从用户的角度来看,最终合同已损坏。它保持最终。首先,字段初始化,然后无法更改。顺便说一句:有很多API使用这个概念,其中一个是JAXB(JDK的一部分)。

5 个答案:

答案 0 :(得分:7)

在构造对象并保存在对象本身中获得的注释字段集之后,或者通过将类的单独映射保留到注释字段集时,如何执行步骤1到3?

然后,当您需要更新对象中的注入字段时,从对象或单独的地图中检索集合并执行步骤4.

答案 1 :(得分:1)

另一种选择,正如您所说,从一开始就知道几个有关的领域,就是只询问那些领域或方法。

示例:请参阅java/lang/Class.html

中的getDeclaredMethodgetDeclaredField

答案 2 :(得分:1)

不知道它是否有用,但this project看起来会像你想要的那样。引用:

  

一组反射实用程序和   与...有关的杂项公用事业   与班级及其领域合作   没有依赖关系   兼容java 1.5和泛型。

     

实用程序缓存反射数据   用于高性能操作但是   使用弱/软缓存来避免   持有开放的ClassLoaders并导致   缓存存在于内存中   永久性。覆盖的能力   你自己的缓存机制是   支撑。

答案 3 :(得分:0)

您可以利用允许在对象构造上注入依赖关系的现有框架。例如Spring allows to do that与aspectj编织。一般的想法是你在spring级别定义bean依赖项,只是标记目标类以建议它们的对象创建。实际依赖性解析逻辑直接注入类字节代码(可以使用编译或加载时编织)。

答案 4 :(得分:0)

使用反射执行任何操作的最快方法是尽可能缓存实际的Reflection API类。例如,我最近制作了一个又一个动态的POJO操纵器,我认为这是每个人最终在某些方面做的事情之一,这使我能够做到这一点:

Object o = ...
BeanPropertyController c = BeanPropertyController.of(o);

for (String propertyName : c.getPropertyNames()) {
        if (c.access(propertyName) == null && 
            c.typeOf(propertyName).equals(String.class)) {
                c.mutate(propertyName, "");
        }
}

它的工作方式是它基本上有一个控制器对象延迟加载bean的所有属性(注意:一些魔法涉及)然后重用它们,只要实际的控制器对象是活。我只能说,通过保存Method对象本身,我设法把那件事变成了一个该死的快事,我为此感到自豪,甚至考虑发布它,假设我可以设法解决版权等问题。