2009-10-28 47 views
5

假设,我有很多类,它们是使用Java反射构造的(出于某种原因)。现在我需要将值后注入字段,这些字段是 ,注释号为@PostInjectJava:什么是使用反射注入字段的最快方法?

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);

恐怕让所有领域,是做最慢的事情。
当我从一开始就知道它时,我可以有人获得一个领域吗?

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

注2:为什么我想要post-field注入:从API用户的角度来看,它必须可以使用final字段。此外,当API先验地不知道字段的类型和数量时,使用接口不可能实现字段初始化。

NOTE2b:从视用户的角度来看,最终的合同是破碎。它保持最终状态。首先,一个字段被初始化,然后它不能被改变。顺便说一句:有很多API使用这个概念,其中一个是JAXB(JDK的一部分)。

+0

我只是好奇你为什么需要这样做?这个背后有一个有趣的故事,如果有,你能分享吗? – 2009-10-28 12:10:49

+0

我正在编写一个类似于JAXB的编组器,但更特别(因此更受限制)。带注释的POJO非常灵活。 – 2009-10-28 12:21:17

+1

如果你要求实现者使用你的注释 - 你在这里并没有真正获得使用接口的任何东西 - 并且你没有真正使用POJO - http://en.wikipedia.org/wiki/Plain_Old_Java_Object#Contextual_variations – Nate 2009-10-28 12:50:15

回答

7

在构建对象并保存您在对象本身中获得的注释字段集合或保留一组单独的类到注释字段集合之后,如何执行步骤1到3?

然后,当你需要更新注入的领域中的对象,无论从对象或单独的地图检索设定和执行步骤4.

+0

完美的主意! – 2009-10-28 12:18:13

1

+1我喜欢RSP的想法。


另一个选择,正如你所说,你知道从一开始就关注的几个领域,就是只问这些领域或方法。

举例:详见getDeclaredMethodgetDeclaredFieldjava/lang/Class.html

1

不知道,如果它的任何好处,但this project看起来像它会做你想要什么。报价:

一组反射公用事业和 相关 杂公用事业类和各自领域的 没有依赖关系是 与Java 1.5和泛型兼容工作。

公用事业缓存反射数据 高性能操作,但使用 弱/软缓存以避免 保持开放类装入器并且使得所述 在内存中缓存 存在永久。支持使用您自己的缓存机制覆盖 的能力是 。

0

您可以利用现有的框架允许注入对象构造的依赖关系。例如Spring allows to do that与aspectj编织。总体思路是,你可以在spring层次上定义bean的依赖关系,并且只标记目标类,以便为他们的对象创建提供建议。实际的依赖关系解析逻辑直接注入类字节码(可以使用编译或加载时编织)。

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对象本身,我设法将这件事情变成了一件该死的事情,我为此感到非常自豪,甚至考虑释放它,假设我能够设法解决版权问题等。

相关问题