我讨厌JavaBeans模式的激情像一千个太阳的火焰一样燃烧。为什么呢?
我想要的是:
class Customer {
public Property<String> name = new Property();
}
我主要是网络开发人员,因此需要JPA和Wicket支持。
帮我离开javabean火车!
答案 0 :(得分:10)
我认为你与你在那里的宣言非常接近(见下面的草图)。但是,通过使用非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#等等可能仍然是更好的选择。
答案 1 :(得分:4)
在
查看我的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,observers,delegates,mixins等。
它是一组注释和注释处理器,可以在eclipse或命令行构建中运行(例如在ant中)。处理器生成一个超类来包含所有生成的代码(注释处理器不能更改包含注释的类,顺便说一句)
答案 2 :(得分:3)
您可能需要查看Groovy - 一种具有“真实”属性的动态类型,基于JVM(和完全兼容Java)的语言。
答案 3 :(得分:2)
使用Spring Framework。它的目的是通过抽象你抱怨的许多基础来简化Java开发。
您可以将它与Hibernate一起使用,这样可以简化与数据源的交互。
有用的网站:
www.springsource.org/download
www.hibernate.org /
答案 4 :(得分:1)
答案 5 :(得分:1)
当我第一次使用C#时,我喜欢这些属性,但是现在,在使用VS 2008一段时间之后,我不得不说我更喜欢set- / get-methods。
重点是我个人的工作方式。当我有一个新类并且我想知道我能用它做什么时,我只需输入classname.set,Eclipse就会向我显示我可以更改的“属性”。同样可以获得。也许它只是可怜的VS方式,但在那里我必须通过这个itelisense的长列表(其中所有内容混合,而不是首先显示属性)只是为了找出我编译后我想要设置的属性是readonly。 ..doh!
是的,在Java中你需要很多行,但我只是编写我的属性并告诉IDE“请为我创建getter和setter”。但是这些方法往往会占用大量空间,这就是为什么我想在Java中使用区域,以便我可以在IDE中折叠。
答案 6 :(得分:0)
您还可以构建一个代码生成器,从您编写的DSL创建.java类。您可以使用某种标记来描述类的名称,所需的属性及其类型。然后,使用生成javabeans的程序处理该文件。或者你可以使用注释,并使用类似ASM的东西对类文件进行后处理以注入访问器和放大器。存取器。我也相信Spring提供了一些这样的功能,但我没有使用它们。
答案 7 :(得分:0)
从JBoss尝试SEAM框架,您应该喜欢它。
答案 8 :(得分:0)
我试过这个:
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;
}
}
答案 9 :(得分:0)
我在我的模型实体(使用JPA注释)上大量使用JavaBean属性,以便能够将它们数据绑定到UI(使用JFace)。
遗憾的是,我没有针对第二个问题的解决方案(可能除了定义包含属性名称的常量之外)。
我生成监听器样板的方法是让我的模型实体从AbstractJavaBean超类扩展,该超类使用反射来处理它。然后我可以使用创建getter / setter的默认方式,除了setter需要重写如下:
public void setRemarks(String remarks) {
set("remarks", remarks);
}
AbstractJavaBean.set然后使用反射(通过Apache commons beanutils)通过其getter读取属性“remarks”的旧值,将新值设置为名为“remarks”的字段,并使用旧的方法触发属性更改事件和新的价值观。实际上,这个想法可以扩展为使得依赖的“派生”属性能够在属性“birthDate”被更改时基于诸如“age”之类的变化的属性之一自动触发属性更改。所有这些逻辑都可以在AbstractJavaBean中的一个位置编码,并由任何模型对象使用。
答案 10 :(得分:0)
我正在寻找同样的事情,我真的很惊讶我找不到合适的图书馆。由于我经常感到痛苦,所以我在两年前开始了一个解决这些问题的小项目:属性
可从以下位置获取: 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);
}
}