Java:使用反射注入字段的最快方法是什么?
假设,我有很多类,它们是使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在构造对象后立即执行步骤 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.
不知道它是否有任何好处,但是这个项目看起来它会做你想做的事情想。引用:
Don't know if it's any good, but this project looks like it would do what you want. Quote:
正如您所说,您从一开始就知道相关的几个字段,另一种选择是仅询问这些字段或方法。
示例:请参阅 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
orgetDeclaredField
in java/lang/Class.html您可以利用允许注入对象构造依赖项的现有框架。例如 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).
使用反射执行任何操作的最快方法是尽可能缓存实际的反射 API 类。例如,我最近制作了另一个动态 POJO 操纵器,我相信这是每个人最终在某个时刻都会做的事情之一,这使我能够做到这一点:
它的工作方式是它基本上有一个控制器延迟加载 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:
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.