Java:动态属性

时间:2010-02-07 01:35:56

标签: java google-app-engine dynamic properties

女士&们,

我是Java的新手,请原谅我,如果这很明显,但我还没发现很多。

我想在运行时为类创建动态属性(变量)(通过添加或更改属性和方法来定义可在运行时更改的对象)。


原因:我想在GAE中存储一个数据模型,可以在编译应用程序后动态扩展(是的,DataStore允许)。应该添加哪些属性也存储在DataStore中(就像使用机器人来构建机器人......有趣)。

Python允许我在运行时添加属性。 Groovy似乎也允许这样做。 “纯粹的”Java世界中唯一指向该方向的东西似乎是“动态代理”。

但是,如果他们能够做到这一点,我还无法弄清楚。

5 个答案:

答案 0 :(得分:10)

Java无法动态添加属性。它也没有能力在运行时动态创建类或在运行时更改它们。 Java强烈且静态地键入。您可以做的最好的事情是将这些属性放入Map或类似的。

编辑:好的,显然有些澄清是有道理的。 OP特别提到了GAE,这些方法的 none 将起作用,但我会提到它们,因为有些人似乎对他们的缺席不以为然。

Java Compiler API(Java 6+)允许您在运行时编译Java类。从技术上讲,你可以写出一个Java源文件来查看你想要的,编译它并加载它。

Java字节码库可以在运行时重写类。这被JPA(和其他)等库使用。你可以用这种方式修改类。

OP指的是a)参考GAE和b)更多按照Javascript如何允许您通过动态添加,删除或更改属性在运行时修改类或特定实例的顺序。 Java肯定不会这样做,特别是在GAE上没有。

以上内容对此不例外,就像在C ++中将类转换为char *一样,因此您可以阅读私有成员并不意味着C ++没有私有成员。使用这两种方法实际上绕过了Java运行库,即使它们是Java的一部分。

答案 1 :(得分:2)

Java不支持它。最好的办法是在一些外部数据存储中存储/管理,您可以从Java代码中访问这些数据存储。作为基本内置示例,您可以使用在每个请求中加载的java.util.Properties API,或者以定时间隔缓存和重新加载,或以编程方式重新加载。然后,您可以将键值对存储在.properties文件中,该文件只放在类路径中。 Here is a Sun tutorial about the subject

属性文件可能看起来像

key1=value1
key2=value2
key3=value3

如果将它放在类路径中,则可以将其加载为

Properties properties = new Properties();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
properties.load(classLoader.getResourceAsStream("file.properties"));
String key1 = properties.getProperty("key1"); // value1

其他替代方法是例如XML文件(您可以使用任何Java XML API访问)或仅使用数据库(您可以使用JDBC API访问)。

答案 2 :(得分:2)

我不知道这是否是GAE上的一个选项(我没有检查限制)以及这是否符合您的需求但是可以查看来自CGLIB的BeanGenerator类(替代来自DynaBean的丑陋的BeanUtils)。引用"Death to DynaBeans"(看一下帖子):

  

没有人让我的CGLIB金锤   去浪费,我已经检查过了   在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包   (BeanCopierBeanMapBulkBean)。   尽你所能结束暴政   DynaBeans!

答案 3 :(得分:1)

可以使用动态代理。也可以在GAE上执行此操作。

首先创建类“SomeObject”,公开获取和设置属性值的方法(即getProperty(name)和setProperty(name,value))。

然后,创建一个接口“PropertyModel”,其中包含您希望生成的对象具有的方法。

调用TransparentProxy.newInstance(someObjectInstance,MyPropertyModel.class)来创建动态代理。

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

答案 4 :(得分:1)

可以使用DynaClass库来动态创建JavaBeans

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