Подтвердить что ты не робот

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

Дамы и господа,

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

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


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

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

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

4b9b3361

Ответ 1

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

Изменить: Хорошо, видимо, некоторые пояснения в порядке. OP специально упомянул GAE, в котором ни один из этих методов не будет работать, но я упомяну их, поскольку некоторые, похоже, делают исключение из-за их отсутствия.

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

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

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

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

Ответ 2

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

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

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

Ответ 3

Я не знаю, является ли это вариантом для GAE (я не проверял ограничения), и если это подойдет вашим потребностям, но, возможно, посмотрите на BeanGenerator из CGLIB (альтернатива уродливому DynaBean из BeanUtils). Цитирование "Death to 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!

Ответ 4

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

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

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

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

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

Ответ 5

Существует библиотека 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);