JavaBeans的替代品?

我讨厌JavaBeans模式的激情像一千个太阳的火焰一样燃烧。 为什么?

  • 详细 。 这是2009年。我不应该为房产写7 LOC。 如果他们有事件听众,那么请抓住你的帽子。
  • 没有类型安全的参考 。 没有类型安全的方法来引用属性。 Java的全部意义在于它是类型安全的,它最流行的模式并不是所有类型都安全的。

我想要的是:

class Customer { public Property name = new Property(); } 

我主要是一名Web开发人员,因此需要JPA和Wicket支持。

帮助我离开javabean火车!

我认为你与那里的宣言非常接近(见下面的草图)。 但是,通过使用非bean方法,您可能会失去大多数假定JavaBeans协议生效的工具所提供的支持。 请善待。 下面的代码是我的头顶…

 public class Property { public final String name; T value; private final PropertyChangeSupport support; public static  Property newInstance(String name, T value, PropertyChangeSupport support) { return new Property(name, value, support); } public static  Property 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 name = Property.newInstance("name", "", support); public final Property 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()。 其余部分留给读者练习:

  • 正确处理序列化
  • 处理空值检查
  • 如果您关心自动装箱开销,也许可以为primefaces类型添加特化。
  • ?? 我相信还有更多陷阱

另请注意,您可以子类化(通常作为匿名类)并覆盖setValue()以提供其他参数检查。

我认为你不能真正摆脱“字符串引用”,因为这几乎就是反思的全部内容。

可悲的是,在这个时代,这仍然有点像汇编编程……如果你有选择的话,Groovy,C#等等可能仍然是更好的选择。

查看我的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中)。 处理器生成一个超类来包含所有生成的代码(注释处理器不能更改包含注释的类,顺便说一句)

您可能想要查看Groovy – 一种动态类型,基于JVM(和完全Java兼容)的语言,具有“真实”属性。

使用Spring Framework。 它的目的是通过抽象您正在抱怨的许多基础来简化Java开发。

您可以将它与Hibernate一起使用,这将简化与数据源的交互。

实用网站:

http://www.springsource.org/download

http://www.hibernate.org/

对于网络,我建议使用JSON (JavaScript Object Notation),

轻量级数据交换格式

。 这是对JSON?Bean 转换器的引用。

当我第一次使用C#时,我喜欢这些属性,但是现在,经过一段时间使用VS 2008后,我不得不说我更喜欢set- / get-methods。

重点是我个人的工作方式。 当我有一个新类并且我想知道我能用它做什么时,我只需输入classname.set并且Eclipse向我显示我可以更改的“属性”。 同样可以获得。 也许它只是可怜的VS方式,但我必须通过这个itelisense的长列表(其中所有内容混合,而不是首先显示属性)只是为了找出我编译后我想要设置的属性是readonly。 ..doh!

是的,在Java中你需要很多行,但我只是编写我的属性并告诉IDE“请为我创建getter和setter”。 但是这些方法往往会占用大量空间,这就是为什么我想在Java中使用区域,以便我可以在IDE中折叠。

您还可以构建一个代码生成器,从您编写的DSL创建.java类。 您可以使用某种标记来描述类的名称,所需的属性及其类型。 然后,使用生成javabeans的程序处理该文件。 或者您可以使用注释,并使用类似ASM的东西对类文件进行后处理以注入访问器和更改器。 我也相信Spring提供了一些这样的function,但我没有使用它们。

试试JBoss的SEAM框架,你应该喜欢它。

一旦我尝试了这个:

 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  Class generate(Class clazz) { // I used here CGLIB to generate dynamically a class that implements the methods: // getters // setters // addPropertyChangeListener // removePropertyChangeListener } } 

我用它作为这个(这只是一个例子):

 public class Foo { @Inject public Provider 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; } } 

我在我的模型实体(使用JPA注释)上大量使用JavaBean属性,以便能够将它们数据绑定到UI(使用JFace)。

遗憾的是,我没有第二个问题的解决方案(可能除了定义包含属性名称的常量)。

我做的生成监听器样板是通过让我的模型实体从使用reflection处理它的AbstractJavaBean超类扩展而来。 然后我可以使用默认的创建getter / setter的方法,除了setter需要重写,如:

 public void setRemarks(String remarks) { set("remarks", remarks); } 

然后,AbstractJavaBean.set使用reflection(通过Apache commons beanutils)通过其getter读取属性“remarks”的旧值,将新值设置为名为“remarks”的字段,并使用旧值和新值触发属性更改事件。 实际上,这个想法可以扩展为使得依赖的“派生”属性能够在属性“birthDate”更改时基于诸如“age”之类的更改的属性之一自动触发属性更改。 所有这些逻辑都可以在AbstractJavaBean中的一个位置编码,并由任何模型对象使用。

我正在寻找同样的事情,我真的很惊讶我找不到合适的图书馆。 由于我经常感到痛苦,所以我在2年前开始了一个解决这些问题的小项目:属性

它位于: https : //github.com/aditosoftware/propertly 。 我们现在正在使用它。

它提供静态类型,包括generics,不同级别的侦听器,树中导航,动态模型等。 主要优点是模型的描述是静态完成的,因此信息始终可用,并且设计时考虑了可扩展性。 因此,您可以使用自己的注释进行validation,或者定义数据的读取和存储位置。

用法示例:

一个简单的IPropertyPitProvider。 属性是名字,姓氏和年龄。

 // Generics describe parent, self and children public class StudentPropertyPitProvider extends AbstractPPP { // IPropertyDescription gives static access to an IProperty's meta data like name and type. public static final IPropertyDescription FIRST_NAME = PD.create(StudentPropertyPitProvider.class); public static final IPropertyDescription LAST_NAME = PD.create(StudentPropertyPitProvider.class); public static final IPropertyDescription 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 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); } }