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

发布于 2024-08-09 08:30:31 字数 1044 浏览 5 评论 0原文

假设,我有很多类,它们是使用 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);

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

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

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

NOTE2b:从用户的角度来看,最终的合约没有损坏。它保持最终状态。首先,字段被初始化,然后就无法更改。顺便说一句:有很多 API 使用这个概念,其中之一是 JAXB(JDK 的一部分)。

Suppose, I have a lot of classes, which are constructed using Java reflection (for some reason). Now I need to post-inject values to fields, which are
annotated with @PostInject.

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

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

My question is: what is a fast way to set a field using reflection?
Remember, I need to do this very often on a lot of classes, that's
why performance is relevant.

What I would do by intuition is shown by this pseudo-code:

  • get all fields of the class
    clazz.getFields();
  • check, which are annotated with @PostInject
    eachField.getAnnotation(PostInject.class);
  • make these fields accessible
    eachAnnotatedField.setAccessible(true);
  • set them to a certain value
    eachAnnotatedField.set(clazz, someValue);

I'm afraid that getting all fields is the slowest thing to do.
Can I someone get a field, when I know it from the beginning?

NOTE: I can't just let the classes implement some interface, which would
allow to set the fields using a method. I need POJOs.

NOTE2: Why I want post-field injection: From the point of view of an API user, it must be possible to use final fields. Furthermore, when the types and number of fields are not known by the API a priori, it is impossible to achieve field initialization using an interface.

NOTE2b: From the point of view of the user, the final contract is not broken. It stays final. First, a field gets initialized, then it can't be changed. By the way: there are a lot of APIs which use this concept, one of them is JAXB (part of the JDK).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

残疾 2024-08-16 08:30:31

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

然后,当您需要更新对象中的注入字段时,从对象或单独的映射中检索该集并执行步骤 4。

How about doing steps 1 to 3 just after you constructed the object and saving the set of annotated fields that you obtain either in the object itself or by keeping a separate map of class to set-of-annotated-fields?

Then, when you need to update the injected fields in an object, retrieve the set from either the object or the seperate map and perform step 4.

忘年祭陌 2024-08-16 08:30:31

不知道它是否有任何好处,但是这个项目看起来它会做你想做的事情想。引用:

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

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

Don't know if it's any good, but this project looks like it would do what you want. Quote:

A set of reflection utilities and
miscellaneous utilities related to
working with classes and their fields
with no dependencies which is
compatible with java 1.5 and generics.

The utilities cache reflection data
for high performance operation but
uses weak/soft caching to avoid
holding open ClassLoaders and causing
the caches to exist in memory
permanently. The ability to override
the caching mechanism with your own is
supported.

骷髅 2024-08-16 08:30:31

正如您所说,您从一开始就知道相关的几个字段,另一种选择是仅询问这些字段或方法。

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

Another option, as you say you know the few fields concerned from the beginning, is to ask only for those fields or methods.

Example : see getDeclaredMethod or getDeclaredField in java/lang/Class.html

云胡 2024-08-16 08:30:31

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

You can exploit existing frameworks that allow to inject dependencies on object construction. For example Spring allows to do that with aspectj weaving. The general idea is that you define bean dependencies at spring level and just mark target classes in order to advise their object creation. Actual dependency resolution logic is injected directly to the class byte-code (it's possible to use either compile- or load-time weaving).

留一抹残留的笑 2024-08-16 08:30:31

使用反射执行任何操作的最快方法是尽可能缓存实际的反射 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 对象本身,我成功地将它变成了一个非常快的东西,我对此感到非常自豪,甚至考虑发布它,假设我可以设法解决版权等问题。

Fastest way to do anything with reflection is to cache the actual Reflection API classes whenever possible. For example I very recently made a yet-another-dynamic-POJO-manipulator which I believe is one of those things everyone ends up doing at some point which enables me to do this:

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, "");
        }
}

The way it works is that it basically has that one controller object which lazyloads all the properties of the bean (note: some magic involved) and then reuses them as long as the actual controller object is alive. All I can say is that by just saving the Method objects themselves I managed to turn that thing into a damn fast thing and I'm quite proud of it and even considering releasing it assuming I can manage to sort out copyrights etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文