Java: динамические свойства

Дамы И Господа,

Я новичок в Java, простите меня, если это очевидно, но я не нашел много об этом.

ID, как создать динамические свойства (переменные) класса во время выполнения (определите объект, который может быть изменен во время выполнения, путем добавления или изменения свойств и методов).


причина: я хочу сохранить модель данных в GAE, которая может быть расширена динамически после компиляции приложения (да, хранилище данных позволяет это). Какое свойство должны быть добавлены хранятся в хранилище данных, а также (его, как с помощью роботов для построенных роботов...смешной.)

Python позволяет мне добавлять свойства во время выполнения. Groovy, кажется, позволяет это тоже. Единственное, что в" чистом "мире Java указывает в этом направлении, кажется, "динамические Прокси".

но я еще не мог понять, делают ли они трюк.

5 ответов


Java не имеет возможности динамически добавлять свойства. Не имеет возможность динамически создавать классы во время выполнения или изменять их во время выполнения. Java сильно и статически типизирован. Лучшее, что вы можете сделать, это поместить такие свойства в Map или аналогичные.

Edit: хорошо, по-видимому, некоторые разъяснения в порядке. В ОП конкретно упоминается GAE, который нет из этих методов будет работать, но я упомяну их, так как некоторые кажутся чтобы возразить против их отсутствия.

на API компилятора Java (Java 6+) позволяет компилировать классы Java во время выполнения. Технически вы можете написать исходный файл Java, чтобы выглядеть именно так, как вы хотите, скомпилировать его и загрузить.

байт-код Java-библиотек можно переписать в Java. Это используется такими библиотеками, как JPA (и другими). Вы можете изменить классы таким образом.

что OP имеет в виду, однако, a) в отношении работы на GAE и b) больше в порядке того, как Javascript позволяет изменять классы или конкретные экземпляры во время выполнения путем динамического добавления, удаления или изменения свойств. Java, конечно, не делает этого и конкретно не делает на GAE.

вышеизложенное не является исключением из этого, как и приведение класса к char * в C++, чтобы вы могли читать частные члены, не означает, что C++ не имеет частных членов. Вы по существу обходите Java runtime с обоими этими методами даже хотя они являются частью Java.


Java не поддерживает его. Лучше всего хранить / управлять в некотором внешнем хранилище данных, к которому вы можете получить доступ изнутри кода Java. В качестве основного и встроенного примера вы можете использовать java.util.Properties API, который вы загружаете по каждому запросу или кэшируете и перезагружаете через определенные интервалы времени или перезагружаете программно. Затем вы можете сохранить пары ключ-значение в .properties файл, который вы просто помещаете в путь к классам. вот Sun учебник по этой теме.

A файл свойств может выглядеть как

key1=value1
key2=value2
key3=value3

если вы поместите его в classpath, то вы можете загрузить его как

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


Я не знаю, является ли это опцией на GAE (я не проверял ограничения), и если это будет соответствовать вашим потребностям, но, возможно, посмотрите на BeanGenerator класс из CGLIB (альтернатива уродливому DynaBean С BeanUtils). Цитата "смерть DynaBeans" (взгляните на сообщение):

Не один, чтобы мой CGLIB золотой молоток пропадать, я проверил в классе BeanGenerator в CVS. Вы использовать это вроде так:

BeanGenerator bg = new BeanGenerator();
bg.addProperty("foo", Double.TYPE);
bg.addProperty("bar", String.class);
Object bean = bg.create();

сгенерированный класс является реальные JavaBean, что означает, что вы можете использовать стандартные утилиты фасоли. Это включает все классы в (BeanCopier, BeanMap и BulkBean). Сделайте свою часть, чтобы положить конец тирании Динабианцы!


возможно использование динамических Прокси. Это также возможно сделать на GAE.

сначала создайте класс "SomeObject", который предоставляет методы для получения и установки значений свойств (т. е. getProperty(name) и setProperty(name, value)).

затем создайте интерфейс "PropertyModel", содержащий методы, которые вы хотели бы, чтобы ваши сгенерированные объекты имели.

Вызовите TransparentProxy.newInstance (someObjectInstance, MyPropertyModel.класса) для создания динамический прокси.

что происходит, так это то, что Java расширит ваш объект someObjectInstance с указанным интерфейсом (btw. вы можете указать более одного). Когда вы вызываете метод на прокси-объект, вызов метода будет перенаправлен на "вызов(...) "метод, определенный ниже, вам нужно будет изменить этот код для обработки как геттеров, так и сеттеров и включить некоторую обработку исключений и т. д. Но в целом, это способ работы динамических прокси в 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());
}
}

здесь 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);