JavaBean到底是什么?

我理解,我认为,"Bean"是一个Java类,具有属性和getter/setter。
据我所知,它相当于Cstruct。是真的吗?

此外,JavaBean和普通class之间是否存在真正的句法差异?
是否有任何特殊的定义或Interface

基本上,为什么有这样一个术语?

Serializable接口是什么意思?

740155 次浏览

JavaBean只是一个标准。它是一个常规的Javaclass,除了它遵循某些约定:

  1. 所有属性都是私有的(使用getters/setters
  2. 公共无参数构造函数
  3. 实现#0

就是这样。这只是一个惯例。不过很多图书馆都依赖它。

关于Serializable,从API留档开始:

类的可序列化性由实现java.io.Serializable接口接口不会将其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的序列化接口没有方法或字段,仅用于确定可序列化的语义学。

换句话说,可序列化对象可以写入流,因此可以写入文件、对象数据库等任何东西。

此外,JavaBean和另一个类之间没有语法上的区别——如果一个类遵循标准,它就是JavaBean。

它有一个术语,因为该标准允许库以编程方式处理你以预定义方式定义的类实例。例如,如果一个库想流式传输你传递给它的任何对象,它知道它可以,因为你的对象是可序列化的(假设库要求你的对象是正确的JavaBeans)。

有一个术语让它听起来很特别。现实远没有那么神秘。

基本上,一个“Bean”:

  • 是一个可序列化的对象(也就是说,它实现了#0,并且正确地实现了),即
  • 具有“属性”,其getter和setter只是具有某些名称的方法(例如,getFoo()是“Foo”属性的getter),并且
  • 有一个公共零参数构造函数(因此可以随意创建它并通过设置其属性进行配置)。

至于Serializable:那只不过是一个“标记接口”(一个不声明任何函数的接口),它告诉Java实现类同意(并暗示它能够)“序列化”——一个将实例转换为字节流的过程。这些字节可以存储在文件中,通过网络连接发送等,并且有足够的信息允许JVM(至少知道对象类型的接口)稍后重建对象——可能在应用程序的不同实例中,甚至在整个其他机器上!

当然,类还需要遵守一些限制,其中最主要的就是所有的实例字段要么是基本类型(int, bool等),要么是某个类的可序列化实例,要么标记为transient,这样Java就不会尝试包含它们。(这当然意味着transient字段将无法在流中存活。有transient字段的类应该准备好在必要时重新初始化它们。)

不能遵守这些限制的类不应该实现Serializable(而且,IIRC,Java编译器甚至不会这样做。)

关于你问题的第二部分,序列化是一种持久性机制,用于将对象存储为有符号字节序列。不太正式地说,它存储对象的状态,以便您稍后可以通过反序列化检索它。

JavaBeans是Java类,它们遵循非常简单的编码约定。你需要做的就是

  1. 实现java.io.Serializable接口-保存对象
  2. 使用公共空参数构造函数-实例化对象
  3. 提供公共getter/setter方法-获取和设置私有变量(属性)的值。

在跨多个服务器部署项目时,您会发现序列化很有用,因为bean将在它们之间持久化和传输。

要理解JavaBean,您需要注意以下几点:

JavaBean是概念性的东西,不能代表一类特定的东西

JavaBean是一个开发工具,可以可视化操作可重用的软件组件

JavaBean基于Sun JavaBeans规范,可以是可重用的组件。它最大的特点是可重用性。

JavaBeans用于更少的代码和更多的工作方法。

JavaBeans在整个JavaEE中用作运行时发现和访问的通用契约。例如,JavaServer Pages(JSP)使用JavaBeans作为页面之间或servlet和JSP之间的数据搬迁对象。JavaEE的JavaBeans Activation Framework使用JavaBeans将对MIME数据类型的支持集成到JavaEE中。JavaEE Management API使用JavaBeans作为在JavaEE环境中管理资源检测的基础。

关于序列化:

在对象序列化中,对象可以表示为字节序列,其中包括对象的数据以及有关对象类型和存储在对象中的数据类型的信息。

序列化对象写入文件后,可以从文件中读取并反序列化,即表示对象及其数据的类型信息和字节可用于在内存中重新创建对象。

JavaBeans的属性

JavaBean是满足某些编程约定的Java对象:

  1. JavaBean类必须实现SerializableExternalizable

  2. JavaBean类必须有一个无arg构造函数

  3. 所有JavaBean属性必须具有公共setter和getter方法

  4. 所有JavaBean实例变量都应该是私有的

JavaBeans示例

@Entitypublic class Employee implements Serializable{
@Idprivate 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. 类必须有一个公共默认构造函数(没有参数)。这允许在编辑和激活框架中轻松实例化。

  2. 根据标准命名约定,类属性必须可以使用get、set、is(可用于布尔属性而不是get)和其他方法(所谓的访问器方法和修改器方法)访问。这允许在框架中轻松自动检查和更新bean状态,其中许多框架包括各种类型属性的自定义编辑器。Setter可以有一个或多个参数。

  3. 类应该是可序列化的。(这允许应用程序和框架以独立于VM和平台的方式可靠地保存、存储和恢复bean的状态。)

有关更多信息,请参阅此链接

用一个例子解释。

1.导入java.io.Serializable

至于序列化,请参阅留档

2.私人领域

字段应该是私有的,以防止外部类轻松修改这些字段。而不是直接访问这些字段,通常使用getter/setter方法。

3.构造器

没有任何参数的公共构造函数。

4. getter/setter

用于访问和修改私有字段的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 */// getterpublic int getId() {return id;}public String getName() {return name;}// setterpublic void setId(int id) {this.id = id;}public void setName(String name) {this.name = name;}}

它们是可序列化的,具有零参数构造函数,并允许使用getter和setter方法访问属性。这个标准被命名为“Bean”,旨在为Java创建可重用的软件组件。

构成应用程序主干并由SpringIOC容器管理的对象称为bean。bean是由Spring IoC容器实例化、组装和以其他方式管理的对象。否则,bean只是应用程序中许多对象之一。根据Spring IoC

JavaBeans是一个标准,它的基本语法要求已经被其他答案清楚地解释了。

然而,JavaBeans的真正含义或预期用途是,以及围绕该标准的各种工具支持,以促进代码重用和基于组件的软件工程,即使开发人员能够通过组装现有组件(类)来构建应用程序,而无需编写任何代码(或只需要编写一点胶水代码)。不幸的是,这项技术被业界低估和利用不足,这可以从本线程的答案中看出。

如果您阅读Oracle的JavaBeans教程,您可以更好地理解它。

JavaBean是一个Java类(概念类),应该遵循以下约定:

  1. 它应该有一个无参数构造函数。
  2. 它应该是可序列化的。
  3. 它应该提供设置和获取属性值的方法,称为getter和setter方法。

它是一个可重用的软件组件。它可以将多个对象封装到一个对象中,以便可以从多个地方访问同一个对象,是朝着代码易于维护迈出的一步。

JavaBean是满足以下三个条件的任何Java类:

  1. 它应该实现可序列化接口(Marker接口)。
  2. 构造函数应该是公共的,没有参数(其他人称之为“无参数构造函数”)。
  3. 它应该有getter和setter。

值得注意的是,序列版本UID字段对于维护对象状态很重要。

下面的代码符合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 argumentspublic 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早期作为构建GUI的一部分而发明的。它们遵循的模式很容易被工具拆开,让它们创建一个属性面板,以便您可以编辑Bean的属性。一般来说,Bean属性代表屏幕上的一个控件(想想x、y、宽度、高度、文本…)

您也可以将其视为强类型数据结构。

随着时间的推移,这些对于许多使用相同类型访问的工具变得有用(例如,Hibernate将数据结构持久化到数据库)

随着工具的发展,他们更多地转向注释,而不是拆开setter/getter名称。现在大多数系统不需要bean,他们可以使用任何带有注释属性的普通旧Java对象来告诉他们如何操作它们。

现在我将bean视为带注释的属性球——它们实际上只对它们携带的注释有用。

Bean本身并不是一种健康的模式。它们本质上破坏了封装,因为它们将所有属性暴露给外部操作,并且当它们被使用时,有一种趋势(绝不是要求)创建代码来外部操作bean,而不是在bean内部创建代码(违反了“不要向对象询问其值,而是要求对象为你做某事”)。使用带有最小getter和没有setter的注释POJO更像是OO恢复封装,并且具有不变性的可能性。

顺便说一下,当所有这些事情发生时,有人将这个概念扩展到名为EnterpriseJavaBeans的东西。这些是……不同的。它们足够复杂,以至于许多人觉得他们不理解整个Bean概念,并停止使用这个术语。这就是,我认为,为什么你通常听到bean被称为POJO(因为每个Java对象都是POJO,这在技术上是可以的,但是当你听到有人说POJO时,他们通常会想到遵循bean模式的东西)

要使Java类可用作Javabean,其方法名称需要应符合属性方法事件的JavaBeans指南(也称为设计模式)。该类需要是公共类才能被任何Beanbox工具或容器访问。容器必须能够实例化它;如果类是公共的,即使没有提供显式的公共零参数构造函数,容器也应该能够这样做。(没有显式构造函数的Java公共类有一个默认的公共零参数构造函数。)因此,最低限度地说,一个Java的公共类,即使以属性作为唯一成员(当然,还需要附带公共getter和setter)或公共方法作为唯一成员,也是一个Javabean。该属性可以是只读属性(它有getter方法但没有setter)或只写属性(只有setter方法)。Java以公共事件侦听器注册方法为唯一成员的公共类也是一个Javabean。JavaBeans规范不要求如果这样的Java类有明确的公共构造函数,它应该是零参数的。如果可以提供一个包含序列化实例的文件(扩展名为. ser),Beanbox工具可能能够使用该文件实例化原型bean。否则,该类将需要一个显式或默认的构造函数,即公共和零参数。

一旦bean被实例化,JavaBeans API(java.beans.*)就可以对其进行内省并调用其方法。如果没有实现接口BeanInfo或扩展BeanInfo实现的类(例如SimpleBeanInfo类)可用,则内省涉及使用反射(隐式内省)来研究目标bean支持的方法,然后应用简单的设计模式(指南)从这些方法中推断出支持哪些属性、事件和公共方法。如果实现接口BeanInfo的类(对于bean Foo,它必须命名为FoBeanInfo)可用,则API绕过隐式内省并使用该类的公共方法(getTyDetptor()、getMenodExplptors()、getEventSetExplptors())来获取信息。如果一个扩展SimpleBeanInfo的类可用,这取决于哪个SimpleBeanInfo公共方法(getProperties tyDetptor()、get老兄描述符()、getEventSet描述符())被覆盖,它将使用这些被覆盖的方法来获取信息;对于未被覆盖的方法,它将默认为相应的隐式内省。即使没有对bean进行隐式内省,也需要实例化它。因此,公共零参数构造函数的要求。但是,当然,识别它不需要Serializable或Externalizable接口。然而,JavaBeans规范说,“我们也希望它对于一个微小的Bean的常见情况来说是“微不足道的”,它只是想保存它的内部状态而不想考虑它。”所以,所有的bean都必须实现Serializable或Externalizable接口。

总的来说,JavaBeans规范对bean的构成并不难。“编写JavaBeans组件出奇地容易。你不需要特殊的工具,也不必实现任何接口。编写bean只是遵循某些编码约定的问题。你所要做的就是让你的类看起来像bean——使用bean的工具将能够识别和使用你的bean。”简单地说,即使是下面的类也是一个Javabean,

public class Trivial implements java.io.Serializable {}

到目前为止的描述是JavaSE版本(JavaBeans)。如下所述,bean是JavaEE版本。这些版本是基于上面解释的基本思想构建的。特别是,他们考虑的一个主要想法是,如果bean构造函数确实有一些参数怎么办。这些参数可以是简单类型、类/接口类型,也可以两者兼而有之。应该有一种方法让容器知道它可以在实例化bean时替换参数的值。这样做的方法是程序员可以通过注释或XML配置文件或两者的混合来配置(指定值)。

春豆

Spring bean在Spring IoC容器中运行。程序员可以通过XML配置文件、注释或两者的混合进行配置。

在Spring中,如果bean构造函数具有简单类型或类/接口类型参数,则可以以类型安全的方式将值分配为字符串(在前一种情况下作为构造函数参数元素的<value>属性,在后一种情况下作为构造函数参数的<idref>元素)。引用其他Spring bean(称为协作者;通过构造函数参数元素中的<ref>元素)基本上是依赖注入,也是类型安全的。显然,依赖项(协作bean)可能有一个带有注入参数的构造函数;那些注入的依赖项可能有一个带有参数的构造函数等等。此场景最终应终止于注入的依赖项(ies),这些依赖项是容器可以通过构造来实例化的原型bean。

JSF管理Beans

JSF托管bean在Web容器中运行。它们可以使用@ManagedBean注释或应用程序配置资源文件进行配置managed-bean.xml.JSF规范仅支持通过资源注入(而不是类型安全)进行注入。此注入不适合在构造函数上注入。无论如何,规范要求JSF托管bean必须具有公共零参数构造函数。此外,它说,“从本规范的2.3版开始,本节指定的托管bean设施的使用是强烈的“换句话说,应该使用CDI托管bean,它确实在类似于Spring bean的构造函数上提供类型安全的依赖注入。CDI规范采用托管Beans规范,适用于JEE平台的所有容器,而不仅仅是Web层。因此,Web容器需要实现CDI规范。

管理Beans

下面是从托管Bean规范中提取的内容“托管Bean是具有最低要求的容器管理对象,它们可以被看作是JavaSE平台上的JavaBeans组件模型的JavaEE平台增强版本…读者不会错过Manage Beans在JavaServer Faces(JSF)技术中发现的同名设施中具有前身……本规范中定义的Manage Beans代表了JSF中发现的那些的泛化;特别是,Manage Beans可以在JavaEE应用程序中的任何地方使用,而不仅仅是在Web模块中。例如,在基本组件模型中,托管Bean必须提供无参数构造函数,但构建在托管Bean上的规范,如CDI(JSR-299),可以放宽这一要求,允许托管Bean为构造函数提供更复杂的签名,只要它们遵循一些定义良好的规则……托管Bean不能是:最终类、抽象类或非静态内部类。因此,托管Beans的规范,也称为POJO或POJO bean,允许像CDI一样进行扩展。

CDI Beans

CDI规范将托管bean重新定义为:在JavaEE中运行时,如果顶级Java类满足以下要求,则它是托管bean:

它不是内部类。它是一个非抽象类,或者被注释为@Decorator。它不执行javax.enterprise.inject.spi.扩展。•它不是注释@Vetoed或在注释@Vetoed的包中。它有一个适当的构造函数:类有一个没有参数的构造函数,或者类声明了一个带注释的构造函数@Inject。

满足这些条件的所有Java类都是托管bean,因此没有特殊声明需要定义托管bean。

如果它被任何定义为托管bean其他JavaEE规范和if

•它没有使用EJB组件定义注释进行注释或声明为EJB bean类ejb-jar.xml.

Bean构造函数可以具有简单类型参数,因为可以使用@Inject注释注入简单类型。

ejb

EJB在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的bean。

实际上,Beans只是方便使用的对象。序列化它们意味着能够轻松地持久化它们(以易于恢复的形式存储)。

Beans在现实世界中的典型用途:

  • 简单可重用对象POJO(普通旧Java对象)
  • 视觉对象
  • Spring使用Beans处理对象(例如,需要在会话中序列化的User对象)
  • EJB(EnterpriseJavaBeans),更复杂的对象,如JSF Beans(JSF是旧的相当过时的技术)或JSP Beans

因此,实际上,Beans是只是一个惯例/标准,它期望从Java对象中得到它将表现的东西(序列化),并给出一些以某种方式改变它的方法(属性的设置器)。

如何使用它们,只是你的发明,但我上面列出的最常见的案例。

POJO(普通的旧Java对象):POJO是普通的Java对象,除了Java语言强制的限制之外,没有其他限制。

序列化:它用于对象的保存状态并通过网络发送。它将对象的状态转换为字节流。我们可以通过称为反序列化的进程从字节流中重新创建一个Java对象。

使你的类实现java.io.Serializable接口。并使用ObjectOutputStream类的写对象()方法来实现序列化。

JavaBean类:它是一个特殊的POJO,有一些限制(或约定)。

  1. 执行序列化
  2. 有公共无参数构造函数
  3. 所有属性都使用公共getter和setter方法私有。

许多框架(如Spring)使用JavaBean对象。

JavaBean是JavaBeans架构中的组件或基本构建块。JavaBeans架构是一种组件架构,它受益于基于组件的方法的可重用性和互操作性。

一个有效的组件体系结构应该允许从软件构建块(在这种情况下是Beans),可能由不同的供应商提供,也使架构师/开发人员可以选择组件(Bean),了解其功能,并将其合并到应用程序中。

由于类/对象是像Java这样的OOP语言的基本构建块,它们是JavaBeans架构中Bean的自然竞争者。

将普通Java类转换为Javabean的过程实际上只不过是使其成为可重用和可互操作的组件。

  1. 控制暴露给另一个应用程序的类的属性、事件和方法。(您可以有一个BeanInfo类,它只报告外部应用程序需要的那些属性、事件和方法。)
  2. 持久性(可序列化或可外部化-这也意味着具有无参数构造函数,对字段使用瞬态)
  3. 能够注册事件并生成事件(例如,使用绑定和约束属性)
  4. 定制器(通过GUI或提供留档来定制Bean)

为了将Java类命名为Javabean,它们不需要具备上述所有能力。相反,它意味着实现与上下文相关的上述子集(例如,某个框架中的bean可能不需要定制器,其他bean可能不需要绑定和约束属性等)。

Java几乎所有领先的框架和库都隐含地遵循JavaBeans架构,以获得上述好处。

Spring@Bean注释表示一个方法产生一个bean由Spring容器管理。

更多参考:https://www.concretepage.com/spring-5/spring-bean-annotation

如果您熟悉C/Golang,您从未听说过C bean或Go bean,因为它们有struct关键字,开发人员可以轻松定义结构类型,而无需编写复杂的OOP关键字。

type User struct {Name stringAge int}
var user User
user.Name = "name"user.Age = 18
var bytes, err = json.Marshal(user)

缺乏struct类型是Java的错误,开发人员发现了这种严重的短缺。

然后JavaBean被发明为另一个无聊的规则,让class假装struct,和平你的编辑器或编译器不会因为你对类成员的不安全访问而哭泣或大喊大叫。

上面重复了6到7次,JavaBeans需要无参数构造函数。

这是错误的,没有这样的要求,特别是在JavaSpring的上下文中。

在描述JavaBeanns API(https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/)的规范版本(1.01)中也没有提到该要求。更重要的是-该规范在以下上下文中只提到了2次“空构造函数”:"每个定制器都应该有一个空构造函数。"“每个属性编辑器都应该有一个空构造函数。”

因此,看起来规范的作者并不是不知道或不愿意使用术语“null构造函数”,仍然没有在JavaBeans中提到它。

如果你想了解JavaBeans,你首先必须了解软件组件。

软件组件

软件组件是运行特定操作的应用程序的一部分。软件组件也可以是服务的一部分。

一个组成部分是:

  • 耦合(有依赖)
  • Stateful(它保存实例变量的状态)
  • 不是标准化的,它是为特定用例设计的(Java-EE Beans之间的主要区别)
  • 在客户端机器中运行

JavaBeans(Enterprise Beans)

  • 在JavaEE服务器中运行的标准化组件
  • 包括不同的业务逻辑来完成一个特定的服务
  • 简化复杂多层分布式系统的开发

JavaBeans更像是一个管理大系统的概念,这就是为什么他们需要标准化。

概述

来源