我认为,“ Bean”是具有属性和getter / setter的Java类。据我了解,它等效于C结构。真的吗?
另外,有没有真正的句法 bean和常规类之间差异?有没有特殊的定义或接口?
基本上,为什么会有一个术语呢?
还什么的Serializable
接口是什么意思?
我认为,“ Bean”是具有属性和getter / setter的Java类。据我了解,它等效于C结构。真的吗?
另外,有没有真正的句法 bean和常规类之间差异?有没有特殊的定义或接口?
基本上,为什么会有一个术语呢?
还什么的Serializable
接口是什么意思?
Answers:
JavaBean只是一个标准
Serializable
。而已。这只是一个约定。尽管很多图书馆都依赖它。
关于Serializable
,来自API文档:
通过实现java.io.Serializable接口的类,可以启用类的可序列化性。未实现此接口的类将不会对其状态进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
换句话说,可序列化的对象可以写入流,因此可以写入文件,对象数据库,甚至任何东西。
而且,JavaBean和另一个类之间在语法上没有区别-如果一个类遵循标准,则该类就是JavaBean。
之所以有一个术语,是因为该标准允许库以编程方式对您以预定义方式定义的类实例进行操作。例如,如果一个库想流式传输您传递给它的任何对象,它就知道它可以,因为您的对象是可序列化的(假设lib要求您的对象是正确的JavaBeans)。
有一个术语使其听起来特别。现实远没有那么神秘。
基本上是一个“ Bean”:
java.io.Serializable
并正确执行了该操作),getFoo()
是“ Foo”属性的“获取器”),并且更新:
至于Serializable
:那不过是一个“标记接口”(一个没有声明任何函数的接口),它告诉Java实现类同意(并暗示它有能力)“序列化”-一个转换的过程。一个实例转换成字节流。这些字节可以存储在文件中,通过网络连接发送等,并具有足够的信息以允许JVM(至少是一个了解对象类型的人)稍后重新构造对象-可能是在另一个实例中应用程序,甚至在其他机器上!
当然,为了做到这一点,班级必须遵守某些限制。其中最主要的是所有实例字段都必须是原始类型(int,bool等),也可以序列化的某个类的实例或标记为,transient
以便Java不会尝试包含它们。(这当然意味着transient
字段将不能在流中幸存。具有transient
字段的类应准备在必要时重新初始化它们。)
不能由那些遵守限制类不应该实现Serializable
(和,IIRC,Java编译器甚至不会让它这样做。)
transient
部分必须是某种可序列化的类型。
JavaBeans的属性
JavaBean是满足某些编程约定的Java对象:
JavaBean类必须实现Serializable
或
Externalizable
JavaBean类必须具有no-arg构造函数
所有JavaBean属性必须具有公共setter和getter方法
所有JavaBean实例变量都应该是私有的
JavaBeans的例子
@Entity
public class Employee implements Serializable{
@Id
private int id;
private String name;
private int salary;
public Employee() {}
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
举例说明。
1.导入java.io.Serializable
至于序列化,请参阅文档。
2.私人领域
字段应为私有字段,以防止外部类轻松修改这些字段。代替直接访问那些字段,使用通常的getter / setter方法。
3.构造函数
一个没有任何参数的公共构造函数。
4.吸气器/吸气器
用于访问和修改私有字段的Getter和setter方法。
/** 1. import java.io.Serializable */
public class User implements java.io.Serializable {
/** 2. private fields */
private int id;
private String name;
/** 3. Constructor */
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
/** 4. getter/setter */
// getter
public int getId() {
return id;
}
public String getName() {
return name;
}
// setter
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
setId(int id)
是要说this.id = id;
而不是要说的身体this.id = is;
Java Bean用于更少的代码和更多的工作方式... Java Bean在整个Java EE中都被用作运行时发现和访问的通用合同。例如,JavaServer Pages(JSP)使用Java Bean作为页面之间或Servlet和JSP之间的数据传输对象。Java EE的JavaBeans激活框架使用Java Bean将对MIME数据类型的支持集成到Java EE中。Java EE管理API使用JavaBeans作为Java EE环境中要管理的资源检测的基础。
关于序列化:
在对象序列化中,对象可以表示为字节序列,其中包括对象的数据以及有关对象类型和存储在对象中的数据类型的信息。
将序列化的对象写入文件后,可以从文件中读取并反序列化它,即表示对象及其数据的类型信息和字节可用于在内存中重新创建对象。
在跨多个服务器部署项目时,您会发现序列化很有用,因为Bean将被持久化并在它们之间进行传输。
Java Beans是一个标准,其他答案也清楚地说明了其基本语法要求。
但是,IMO不仅仅是一个简单的语法标准。Java Bean的真正含义或预期用途与围绕标准的各种工具支持一起,可促进代码重用和基于组件的软件工程,即使开发人员能够通过组装现有组件(类)来构建应用程序,而无需编写任何组件。代码(或者只需要写一点胶水代码)。不幸的是,该技术被业界低估和未充分利用,可以从该主题的答案中得知。
如果您阅读有关Java Bean的 Oracle 教程,则可以更好地理解。
Java Bean是Java类[概念性],应遵循以下约定:
它是可重用的软件组件。它可以将许多对象封装到一个对象中,以便可以从多个位置访问同一对象,这是朝着轻松维护代码迈出的一步。
只是关于bean概念的一些背景/更新。实际上,许多其他答案都具有其中的含义,但原因却不多。
它们是在Java中作为构建GUI的一部分而发明的。它们遵循易于工具分解的模式,从而使它们可以创建属性面板,以便您可以编辑Bean的属性。通常,Bean属性表示屏幕上的一个控件(认为x,y,width,height,text等)。
您也可以将其视为强类型数据结构。
随着时间的流逝,它们对于使用相同访问类型的许多工具变得很有用(例如,Hibernate将数据结构持久存储到数据库中)
随着工具的发展,它们更多地转向注释,而不是分开设置器/获取器的名称。现在,大多数系统不再需要bean,它们可以使用带有注释属性的任何简单的旧java对象来告诉他们如何操作它们。
现在,我将bean视为带注释的属性球-它们实际上仅对它们带有的注释有用。
豆类本身不是健康的模式。它们破坏了封装的性质,因为它们将所有属性暴露给外部操纵,并且在使用它们时,有一种趋势(绝非必要)来创建代码以在外部操纵Bean,而不是在Bean内部创建代码(违反了“ don不要问一个对象的值,而是要一个对象为您做些事情”。使用带有最小的吸气剂且没有塞子的带注释的pojos,更多的是恢复面向对象的封装并具有不变性的可能性。
顺便说一下,随着所有这些事情的发生,有人将这一概念扩展到了称为Enterprise Java Beans的东西。这些是...不同。而且它们非常复杂,以至于许多人认为他们不了解整个Bean概念,因此停止使用该术语。我想,这就是为什么您通常会听到称为POJO的bean(因为每个Java对象都是POJO,从技术上讲这是可以的,但是当您听到有人说POJO时,他们最常考虑的是遵循bean模式的事物)
Java Bean是满足以下三个条件的任何Java类:
需要注意的是serialVersionUID字段对于维护对象状态很重要。以下代码符合Bean的资格:
public class DataDog implements java.io.Serializable {
private static final long serialVersionUID = -3774654564564563L;
private int id;
private String nameOfDog;
//The constructor should NOT have arguments
public DataDog () {}
/** 4. getter/setter */
// getter(s)
public int getId() {
return id;
}
public String getNameOfDog() {
return nameOfDog;
}
// setter(s)
public void setId(int id) {
this.id = id;
}
public void setNameOfDog(String nameOfDog) {
this.nameOfDog = nameOfDog;
}}
Bean 是 Java类,其方法名称遵循Java Bean准则(也称为设计模式)的属性,方法和事件。。因此,不属于属性定义的Bean类的任何公共方法都是Bean方法。至少,一个Java类(即使具有作为其唯一成员的属性(当然,需要附带公共getter和setter),作为唯一成员的public方法或仅一个公共事件侦听器注册方法)也是Java bean。此外,该属性可以是只读属性(具有getter方法,但没有setter)或只写属性(仅具有setter方法)。Java bean必须是一个公共类,才能对任何beanbox工具或容器可见。容器必须能够实例化;因此,它也必须有一个公共构造函数。在JavaBeans规范不需要Bean具有公用的零参数构造函数(显式或默认),容器即可实例化它。如果您可以提供一个包含序列化实例的文件(扩展名为.ser),则beanbox工具可以使用该文件来实例化原型bean。否则,bean必须具有公共的零参数构造函数,无论是显式的还是默认的。
实例化该bean之后,Java Bean API(java.beans。*)可以对其进行内部检查并在其上调用方法。如果没有实现接口BeanInfo或扩展BeanInfo实现的类SimpleBeanInfo类,则自省涉及使用反射(隐式自省)研究目标Bean支持的方法,然后应用简单的设计模式(准则)从中推论出这些方法支持哪些属性,事件和公共方法。如果有一个实现接口BeanInfo的类(对于Foo,必须将其命名为FooBeanInfo)可用,则API绕过隐式自省,并使用此类的公共方法(getPropertyDescriptor(),getMethodDescriptors(),getEventSetDescriptors())来获取信息。如果扩展SimpleBeanInfo的类可用,根据哪个SimpleBeanInfo公共方法(getPropertyDescriptor(),getMethodDescriptors(),getEventSetDescriptors())被覆盖,它将使用那些被覆盖的方法来获取信息;对于未重写的方法,它将默认为相应的隐式自省。无论如何,即使没有进行隐式自省,也需要实例化Bean。因此,需要公共zeri-args构造函数。但是,当然,并不需要Serializable或Externalizable接口。但是Java Bean规范说:“我们也希望它对于微型Bean的普通情况是“琐碎的”,它只是想要保存其内部状态并且不想考虑它。因此,所有bean必须实现Serializable或Externalizable接口。总体,JavaBeans规范对构成bean的要求并不严格。“编写JavaBeans组件非常容易。您不需要特殊的工具,也不必实现任何接口。编写bean只是遵循某些编码约定的事情。所有要做的就是使类看起来像一个bean-使用bean的工具将能够识别和使用您的bean。” 琐碎地,即使下面的类是Java Bean,
public class Trivial implements java.io.Serializable {}
说,bean构造函数具有一些参数。假设一些是简单类型。容器可能不知道要为它们分配什么值。即使这样做,结果实例也可能不可重用。仅当用户可以像在Spring bean中那样通过注释或xml配置文件配置(指定值)时,这才有意义。并假设某些参数是类或接口类型。同样,容器可能不知道要为其分配什么值。仅当用户可以通过注释或xml配置文件配置(指定特定对象)时,这才有意义。但是,即使在Spring中(通过xml配置文件),将特定对象(带有字符串名称)分配给构造函数参数(构造函数参数的属性或元素)也不是类型安全的;这基本上就像资源注入一样。引用其他Spring bean(称为合作者;通过构造函数参数元素中的元素)基本上是依赖注入,因此是类型安全的。显然,一个依赖项(协作者bean)可能具有一个带有注入参数的构造函数。那些注入的依赖项可能具有带有参数的构造函数,依此类推。在这种情况下,最终,您需要容器可以通过简单地调用new MyBean()实例化的一些bean类(例如,MyBean.class),然后才能通过对构造函数的依赖注入构造其他协作Bean,因此, bean具有公共的零参数构造函数。假设,如果某个容器不支持依赖项注入和/或不允许像Spring中那样通过某些注释或xml配置文件向构造函数分配简单类型的值,Bean构造函数不应具有参数。即使是Spring bean应用程序,也需要一些bean具有公共的零参数构造函数(例如,在您的Spring应用程序没有使用简单类型作为构造函数参数的bean的情况下)。
JSF管理的bean在Web容器中运行。可以使用@ManagedBean批注或应用程序配置资源文件managed-bean.xml来配置它们。但是,它仅支持通过资源注入(不是类型安全)进行注入;不适合在构造函数上注入。的 JSF规范要求托管bean必须具有公共零参数构造函数。进一步说,“从本规范的2.3版开始,强烈建议不要使用本节中指定的托管bean工具。解决同一问题的更好,更紧密集成的解决方案是使用JSR-365中指定的上下文和依赖注入(CDI)。“换句话说,将使用CDI管理的bean,它为构造函数提供了类型安全的依赖注入CDI规范采用了Managed Beans规范,该规范不仅适用于Web层,而且适用于JEE平台的所有容器,因此,Web容器需要实现CDI规范。
这是Managed Bean规范的摘录 “受管Bean是具有最低要求的容器管理对象,否则以缩写词“ POJO”(普通的旧Java对象)而闻名……它们可以看作是Java SE平台上JavaBeans组件模型的Java EE平台增强版本。 …。读者不会错过Managed Bean在JavaServer Faces(JSF)技术中发现的同名功能中的前身。本规范中定义的Managed Bean代表了JSF中所发现的那些的概括。特别是,受管Bean可以在Java EE应用程序中的任何地方使用,而不仅仅是在Web模块中使用。例如,在基本组件模型中,托管Bean必须提供无参数的构造函数,但是要建立在托管Bean之上的规范,例如CDI(JSR-299),可以放宽该要求,并允许Managed Bean为构造函数提供更复杂的签名,只要它们遵循一些明确定义的规则即可。Managed Bean不得为:最终类,抽象类,非静态内部类。与常规JavaBean组件不同,托管Bean可能无法序列化。” 因此,受管Bean的规范(也称为POJO或POJO Bean)允许像CDI中那样进行扩展。
CDI规范将托管Bean重新定义为:在Java EE中运行时,如果满足要求,则顶级Java类是托管Bean:
•它不是内部类。•这是一个非抽象类,或使用@Decorator进行了注释。•它没有实现javax.enterprise.inject.spi.Extension。•它没有注释@Vetoed或在带有注释@Vetoed的程序包中。•它具有适当的构造函数,或者:类具有没有参数的构造函数,或者该类声明带有@Inject注释的构造函数。
满足这些条件的所有Java类都是托管Bean,因此不需要特殊声明即可定义托管Bean。要么
是否通过其他任何Java EE规范将其定义为托管Bean,以及
•在ejb-jar.xml中,未使用EJB组件定义的注释对其进行注释或将其声明为EJB bean类。
与Spring Bean不同,它不支持简单类型的构造函数,如果它支持使用xml配置文件(例如Spring或任何注释)进行配置,则可能是可行的。
EJB在EJB容器中运行。它的规格表示:“会话Bean组件是托管Bean。”“该类必须具有不带参数的公共构造函数,”它对会话Bean和消息驱动的Bean都说。此外,它说:“会话Bean类是不需要实现SessionBean接口或Serializable接口。” 出于与JSF Bean相同的原因,EJB3依赖项注入基本上是资源注入,JSF Bean不支持带有参数的构造函数,即通过依赖项注入。但是,如果EJB容器实现CDI,则“可选:类可以具有一个附加的带有Inject注释的构造函数,“它对会话Bean和消息驱动的Bean都这样说,因为,”被打包到CDI Bean归档中但没有注释javax.enterprise.inject.Vetoed注释的EJB被认为是支持CDI的豆。”