Я ненавижу паттерн JavaBeans страстью, пылающей, как огонь тысячи солнц. Почему?
Я бы хотел что-то вроде:
class Customer {
public Property<String> name = new Property();
}
Я в основном веб-разработчик, поэтому ему нужна поддержка JPA и Wicket.
Помогите мне сойти с джавабийского поезда!
Я думаю, он имеет в виду, что многие веб-фреймворки и другие вещи в конечном итоге должны ссылаться на них посредством отражения. Я не совсем уверен, как это связано со всем подходом, поскольку это больше похоже на провал фреймворков, чем на что-либо еще.
Не в поезде JavaBean? Шагните по этому пути к платформе C# ...
Поскольку вы упомянули Wicket, я вспомнил, что это: wicketwebbeans.sourceforge.net Может быть, это могло бы вам помочь?




Вы можете попробовать Groovy - динамически типизированный, основанный на JVM (и полностью совместимый с Java) язык с «реальными» свойствами.
Вы также можете создать генератор кода, который создает ваши классы .java из написанного вами DSL. У вас может быть какая-то разметка, описывающая имя вашего класса, необходимые свойства и их типы. Затем обработайте этот файл программой, которая генерирует ваши javabeans. Или вы можете использовать аннотацию и постобработать файлы классов, используя что-то вроде ASM, чтобы внедрить аксессоры и мутаторы. Я также считаю, что Spring предоставляет некоторые из этих функций, но я ими не пользовался.
Определенно подход, который сработает, но я думаю, что он упустил суть сообщения: он считает JavaBeans слишком многословным и сложным. Разве добавление еще одного слоя через DSL или аннотации и постобработка не усугубляет ситуацию?
@ian: DSL может быть неплохой идеей, потому что использование DSL, как правило, делает вещи лаконичными и лаконичными, что в точности соответствует целям плаката.
@ian: В краткосрочной перспективе я бы согласился из-за усилий, необходимых для создания постпроцессора. Однако, как только это будет сделано, код, который его использует, будет проще в запрошенном виде.
Для Интернета я бы предложил JSON (нотация объектов JavaScript),
a lightweight data-interchange format
. Вот ссылка на JSON? Bean переводчик.
Я думаю, вы очень близки с декларацией, которая у вас там (см. Рисунок ниже). Однако при использовании подхода, отличного от bean-компонентов, вы, вероятно, потеряете поддержку, предоставляемую большинством инструментов, предполагающих, что действует протокол JavaBeans. Пожалуйста, будьте добры. Код ниже не у меня в голове ...
public class Property<T> {
public final String name;
T value;
private final PropertyChangeSupport support;
public static <T> Property<T> newInstance(String name, T value,
PropertyChangeSupport support) {
return new Property<T>(name, value, support);
}
public static <T> Property<T> newInstance(String name, T value) {
return newInstance(name, value, null);
}
public Property(String name, T value, PropertyChangeSupport support) {
this.name = name;
this.value = value;
this.support = support;
}
public T getValue() { return value; }
public void setValue(T value) {
T old = this.value;
this.value = value;
if (support != null)
support.firePropertyChange(name, old, this.value);
}
public String toString() { return value.toString(); }
}
а затем продолжайте и используйте его:
public class Customer {
private final PropertyChangeSupport support = new PropertyChangeSupport();
public final Property<String> name = Property.newInstance("name", "", support);
public final Property<Integer> age = Property.newInstance("age", 0, support);
... declare add/remove listenener ...
}
Customer c = new Customer();
c.name.setValue("Hyrum");
c.age.setValue(49);
System.out.println("%s : %s", c.name, c.age);
Итак, теперь объявление свойства - это одна строка кода, и включена поддержка изменения свойства. Я назвал методы setValue () и getValue (), чтобы они по-прежнему выглядели как bean-компонент для кодирования, такого как Rhino и тому подобное, но для краткости вы можете добавить просто get () и set (). Остальное оставим читателю в качестве упражнения:
Также обратите внимание, что вы можете создать подкласс (обычно как анонимный класс) и переопределить setValue (), чтобы обеспечить дополнительную проверку параметров.
Я не думаю, что вам действительно удастся уйти от «ссылок на строки», поскольку именно в этом и заключается суть отражения.
К сожалению, в наши дни это все еще похоже на программирование на ассемблере ... Groovy, C# и т. д. И т. Д. Могут быть лучшим выбором, если у вас есть выбор.
Попробуйте фреймворк Шов от JBoss, он вам должен понравиться.
Однажды я попробовал это:
interface IListenable {
void addPropertyChangeListener( PropertyChangeListener listener );
void removePropertyChangeListener( PropertyChangeListener listener );
}
abstract class MyBean extends IListenable {
public abstract void setName(String name);
public abstract String getName();
// more things
}
public class JavaBeanFactory {
public <T> Class<T> generate(Class<T> clazz) {
// I used here CGLIB to generate dynamically a class that implements the methods:
// getters
// setters
// addPropertyChangeListener
// removePropertyChangeListener
}
}
Я использовал это как это (это просто пример):
public class Foo {
@Inject
public Provider<MyBean> myBeanProvider;
public MyBean createHook(MyBean a) {
final MyBean b = myBeanProvider.get();
a.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
b.setName((String) evt.getNewValue());
}
});
return b;
}
}
Используйте Spring Framework. Его цель - упростить разработку на Java за счет абстрагирования многих оснований, на которые вы жалуетесь.
Вы можете использовать его с Hibernate, что упростит вам взаимодействие с источниками данных.
Полезные сайты:
www.springsource.org/download
www.hibernate.org/
Ознакомьтесь с моими аннотациями Bean на
http://code.google.com/p/javadude/wiki/Annotations
В основном вы делаете такие вещи, как:
@Bean(
properties = {
@Property(name = "name"),
@Property(name = "phone", bound=true),
@Property(name = "friend", type=Person.class, kind=PropertyKind.LIST)
}
)
public class Person extends PersonGen {}
вместо того, чтобы самостоятельно определять все эти дополнительные методы get / set и т. д.
Есть и другие атрибуты для определения equals / hashCode, наблюдателей, делегатов, миксинов и т. д.
Это набор аннотаций и обработчик аннотаций, который работает в eclipse или в сборке из командной строки (например, в ant). Процессор создает суперкласс, содержащий весь сгенерированный код (процессоры аннотаций не могут изменить класс, содержащий аннотации, кстати)
Когда я впервые использовал C#, мне понравились свойства, но теперь, спустя некоторое время, используя их с VS 2008, я должен сказать, что предпочитаю set- / get-методы.
Главное - это мой личный стиль работы. Когда у меня есть новый класс и я хотел бы знать, что я могу с ним сделать, я просто набираю classname.set, и Eclipse показывает мне, какие «Свойства» я могу изменить. То же самое и с получением. Возможно, это просто плохой способ VS, но там мне нужно пролистать длинный список этого itelisense (где все смешано, вместо того, чтобы сначала показывать свойства), чтобы узнать после компиляции, что свойство, которое я хотел установить, доступно только для чтения. ..дох!
Да, в Java вам нужно много строк, но я просто пишу свои атрибуты и говорю IDE: «Пожалуйста, создайте для меня геттеры и сеттеры». Но эти методы, как правило, занимают много места, поэтому я также хотел бы иметь области в Java, которые я мог бы складывать в IDE.
Я часто использую свойства JavaBean для объектов модели (с аннотациями JPA), чтобы иметь возможность привязать их к пользовательскому интерфейсу (с JFace).
К сожалению, у меня нет решения второй проблемы (возможно, кроме определения констант, содержащих имена свойств).
Что я делаю для создания шаблона слушателя, так это то, что объекты моей модели расширяются от суперкласса AbstractJavaBean, который обрабатывает его с помощью отражения. Затем я могу использовать способ создания геттеров / сеттеров по умолчанию, за исключением того, что сеттеры нужно переписать следующим образом:
public void setRemarks(String remarks) {
set("remarks", remarks);
}
Затем AbstractJavaBean.set использует отражение (через beanutils Apache commons) для чтения старого значения свойства "комментарии" через его геттер, устанавливает новое значение в поле с именем "комментарии" и запускает событие изменения свойства, используя старое и новое значения. . Фактически, эта идея может быть расширена, чтобы позволить зависимым «производным» свойствам автоматически запускать изменения свойств, когда одно из свойств, основанное на изменениях, таких как «возраст», изменяется при изменении свойства «BirthDate». Вся эта логика может быть закодирована в одном месте внутри AbstractJavaBean и использоваться любым объектом модели.
Я искал то же самое и был очень удивлен, что не смог найти подходящую библиотеку. Поскольку я регулярно чувствовал боль, 2 года назад я начал небольшой проект по решению этих проблем:
Он доступен по адресу: https://github.com/aditosoftware/propertly. Сейчас мы используем его в нашем продукте.
Он предоставляет статическую типизацию с помощью универсальных шаблонов, слушателей на разных уровнях, навигацию по дереву, динамические модели и многое другое. Основное преимущество состоит в том, что описания моделей выполняются статически, поэтому информация всегда доступна, и они разработаны с учетом расширяемости. Таким образом, вы можете использовать свои собственные аннотации для проверки или определить, откуда данные считываются и хранятся.
Пример использования:
Простой IPropertyPitProvider. Свойства - имя, фамилия и возраст.
// Generics describe parent, self and children
public class StudentPropertyPitProvider
extends AbstractPPP<IPropertyPitProvider, StudentPropertyPitProvider, Object>
{
// IPropertyDescription gives static access to an IProperty's meta data like name and type.
public static final IPropertyDescription<StudentPropertyPitProvider, String> FIRST_NAME =
PD.create(StudentPropertyPitProvider.class);
public static final IPropertyDescription<StudentPropertyPitProvider, String> LAST_NAME =
PD.create(StudentPropertyPitProvider.class);
public static final IPropertyDescription<StudentPropertyPitProvider, Integer> AGE =
PD.create(StudentPropertyPitProvider.class);
// Getters and setters can of course still be used for easier access.
public String getFirstName()
{
// getValue and setValue is available at AbstractPPP. That class is used for easier access.
// Propertly can be used without inheriting from that class, too.
return getValue(FIRST_NAME);
}
public void setFirstName(String pFirstName)
{
setValue(FIRST_NAME, pFirstName);
}
public String getLastName()
{
return getValue(LAST_NAME);
}
public void setLastName(String pLastName)
{
setValue(LAST_NAME, pLastName);
}
public Integer getAge()
{
return getValue(AGE);
}
public void setAge(Integer pAge)
{
setValue(AGE, pAge);
}
}
Используя определенного провайдера:
public class Sample
{
public static void main(String[] args)
{
// Hierarchy is necessary to initialize the IPropertyPitProviders and for advanced features.
Hierarchy<StudentPropertyPitProvider> hierarchy =
new Hierarchy<>("student1", new StudentPropertyPitProvider());
// The created student can be accessed from the hierarchy.
StudentPropertyPitProvider student = hierarchy.getValue();
// Listeners can be added.
student.addPropertyEventListener(new PropertyPitEventAdapter()
{
@Override
public void propertyChanged(IProperty pProperty, Object pOldValue, Object pNewValue)
{
System.out.println(pProperty.getName() + " = " + pNewValue);
}
});
// The following calls will cause
// FIRST_NAME=Nils
// LAST_NAME=Holgersson
// AGE=32
// to be printed on console through the listener.
student.setFirstName("Nils");
student.setLastName("Holgersson");
student.setAge(32);
}
}
Что вы имеете в виду под «Они поощряют ссылки на строки»?