Java:动态属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2215536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: dynamic properties
提问by thomas
Ladies & Gentlemen,
女士们先生们,
I′m new to Java, forgive me if it′s obvious, but I haven′t found much about it.
我是 Java 新手,如果它很明显,请原谅我,但我还没有找到太多关于它的信息。
I′d like to create dynamic properties (variables) for a class at runtime (define an object that can be altered at runtime by adding or changing properties and methods).
我想在运行时为类创建动态属性(变量)(定义一个可以在运行时通过添加或更改属性和方法来更改的对象)。
Reason: I want to store a data model in GAE that can be extended dynamically after compilation of the app (yes, the DataStore allows that). What properties should be added are stored in the DataStore as well (It′s like using Robots to built Robots...funny).
原因:我想在 GAE 中存储一个可以在编译应用程序后动态扩展的数据模型(是的,DataStore 允许这样做)。应该添加的属性也存储在DataStore中(就像使用Robots构建Robots......有趣)。
Python allows me to add properties at Runtime. Groovy seems to allow that, too. The only thing in the "pure" Java world indicating in that direction seems to be "Dynamic Proxies".
Python 允许我在运行时添加属性。Groovy 似乎也允许这样做。在“纯”Java 世界中,唯一指向该方向的似乎是“动态代理”。
But I couldn′t figure out yet if they do the trick.
但我无法弄清楚他们是否做到了这一点。
采纳答案by cletus
Java doesn't have the capability to dynamically add properties. Nor does it have the ability to dynamically create classes at runtime or change them at runtime. Java is strongly and statically typed. The best you can do is put such properties into a Mapor similar.
Java 没有动态添加属性的能力。它也没有能力在运行时动态创建类或在运行时更改它们。Java 是强类型和静态类型的。您能做的最好的事情就是将这些属性放入 aMap或类似的中。
Edit:Ok, apparently some clarifications are in order. The OP specifically mentioned GAE, which noneof these methods will work on but I'll mention them since some seem to take exception to their absence.
编辑:好的,显然需要进行一些说明。该OP特别提到GAE,其中没有一种方法都在工作,但我会提到他们,因为一些人似乎不以为然他们的缺席。
The Java Compiler API(Java 6+) allows you to compile Java classes at runtime. Technically you could write out a Java source file to look exactly how you want, compile it and load it.
在Java编译器API(Java的6+)可以让你在运行时编译Java类。从技术上讲,您可以写出一个 Java 源文件来完全按照您的需要进行编译和加载。
Java bytecode libraries can rewrite classes at runtime. This is used by such libraries as JPA (and others). You could modify classes this way.
Java 字节码库可以在运行时重写类。这被诸如 JPA(和其他)之类的库使用。您可以通过这种方式修改类。
What the OP is referring to however is a) in reference to working on GAE and b) more in the order of how Javascript allows you to modify classes or particular instances at runtime by dynamically adding, removing or change properties. Java certainly doesn't do this and specifically doesn't on the GAE.
然而,OP 所指的是 a) 关于在 GAE 上工作和 b) 更多关于 Javascript 如何允许您在运行时通过动态添加、删除或更改属性来修改类或特定实例的顺序。Java 肯定不会这样做,特别是在 GAE 上不会这样做。
The above is not an exception to this just like casting a class to char *in C++ so you can read private members doesn't mean C++ doesn't have private members. You're essentially bypassing the Java runtime with both of these methods even though they're part of Java.
上面的内容并不是一个例外,就像char *在 C++ 中将类强制转换为这样,您可以读取私有成员并不意味着 C++ 没有私有成员。尽管这两种方法是 Java 的一部分,但您实际上是在绕过 Java 运行时。
回答by BalusC
Java doesn't support it. Your best bet is to store/manage in some external datastore which you can access from inside the Java code. As a basic and builtin example, you can make use of java.util.PropertiesAPI which you load on every request, or cache and reload at timed intervals, or reload programmatically. You can then store the key-value pairs in a .propertiesfile which you just place in the classpath. Here is a Sun tutorial about the subject.
Java 不支持它。最好的办法是在一些可以从 Java 代码内部访问的外部数据存储中进行存储/管理。作为一个基本的内置示例,您可以使用java.util.Properties在每个请求上加载的API,或者按时间间隔缓存和重新加载,或者以编程方式重新加载。然后,您可以将键值对存储在.properties您刚刚放置在类路径中的文件中。这是有关该主题的 Sun 教程。
A properties file can look like
属性文件看起来像
key1=value1 key2=value2 key3=value3
If you put it in the classpath, then you can load it as
如果你把它放在类路径中,那么你可以将它加载为
Properties properties = new Properties();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
properties.load(classLoader.getResourceAsStream("file.properties"));
String key1 = properties.getProperty("key1"); // value1
Other alternatives are for example XML files (which you can access using any Java XML API) or just a database (which you can access using JDBC API).
其他替代方案是例如 XML 文件(您可以使用任何 Java XML API 访问)或仅数据库(您可以使用 JDBC API 访问)。
回答by Pascal Thivent
I don't know if this is an option on GAE (I didn't checked the restrictions) and if this will suit your needs but maybe have a look at the BeanGeneratorclass from CGLIB (an alternative to the ugly DynaBeanfrom BeanUtils). Quoting "Death to DynaBeans"(have a look at the post):
我不知道这是在GAE上的一个选项(我没有检查的限制),如果这将满足您的需求,但也许有一个看看BeanGenerator从CGLIB类(以丑替代DynaBean从 BeanUtils的)。引用“Death to DynaBeans”(看看帖子):
Not one to let my CGLIB Golden Hammer go to waste, I have checked in a BeanGenerator class into CVS. You use it like so:
BeanGenerator bg = new BeanGenerator(); bg.addProperty("foo", Double.TYPE); bg.addProperty("bar", String.class); Object bean = bg.create();The generated class is an realJavaBean, which means you can use standard bean utilities. This includes all of the classes in the
net.sf.cglib.beanspackage (BeanCopier,BeanMap, andBulkBean). Do your part to end the tyranny of DynaBeans!
没有人让我的 CGLIB Golden Hammer 浪费掉,我已经将 BeanGenerator 类签入了 CVS。你像这样使用它:
BeanGenerator bg = new BeanGenerator(); bg.addProperty("foo", Double.TYPE); bg.addProperty("bar", String.class); Object bean = bg.create();生成的类是一个真正的JavaBean,这意味着您可以使用标准的 bean 实用程序。这包括所有类的
net.sf.cglib.beans包(BeanCopier,BeanMap,和BulkBean)。尽自己的一份力量结束 DynaBeans 的暴政!
回答by Mo'in Creemers
It is possible using Dynamic Proxies. It is also possible to do this on GAE.
可以使用动态代理。也可以在 GAE 上执行此操作。
First create the class "SomeObject" that exposes methods to get and set property values (i.e. getProperty(name) and setProperty(name, value)).
首先创建类“SomeObject”,该类公开获取和设置属性值的方法(即getProperty(name) 和setProperty(name, value))。
Then, create an interface "PropertyModel" that contains the methods that you would like your generated objects to have.
然后,创建一个接口“PropertyModel”,其中包含您希望生成的对象具有的方法。
Call TransparentProxy.newInstance(someObjectInstance, MyPropertyModel.class) to create a dynamic proxy.
调用 TransparentProxy.newInstance(someObjectInstance, MyPropertyModel.class) 创建动态代理。
What happens is that Java will extend your object someObjectInstance with the specified interface (btw. you could specify more than one). When you call a method on the proxy object, the method invocation will be redirected to the "invoke(...)" method defined below, you'll need to modify that code to handle both getters and setters and include some exception handling etc. But in general, this is the way dynamic proxies work in Java.
发生的情况是 Java 将使用指定的接口扩展您的对象 someObjectInstance(顺便说一句,您可以指定多个)。当您在代理对象上调用方法时,方法调用将被重定向到下面定义的“invoke(...)”方法,您需要修改该代码以处理 getter 和 setter 并包括一些异常处理等. 但总的来说,这就是动态代理在 Java 中的工作方式。
public class TransparentProxy implements InvocationHandler
{
private final SomeObject someObject;
private TransparentProxy(SomeObject someObject)
{
this.someObject = someObject;
}
public static Object newInstance(SomeObject someObject,
Class<? extends PropertyModel> propertyModel)
{
return Proxy.newProxyInstance(someObject.getClass().getClassLoader(),
new Class[] { propertyModel }, new TransparentProxy(someObject));
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
return this.someObject.getProperty(method.getName());
}
}
回答by bachr
There is DynaClasslibrary that can be used this way to dynamically create JavaBeans
有可以使用这种方式动态创建 JavaBeans 的DynaClass库
Map<Object, Object> properties = new HashMap<Object, Object>();
roperties.put("title", "The Italian Job");
roperties.put("dateOfRelease", "new GregorianCalendar(1969, 0, 1).getTime()");
Object movieBean = BeanCreator.createBeanFromMap(properties);

