我认为,我理解“Bean”是一个具有财产和getters/setter的Java-class。据我所知,它相当于C结构。这是真的吗?

此外,JavaBean和常规类之间是否存在真正的语法差异?是否有特殊定义或接口?

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

Serializable接口是什么意思?


JavaBean只是一个标准。它是一个常规的Java类,但它遵循某些约定:

所有财产都是私有的(使用getters/setter)公共无参数构造函数实现可序列化。

就是这样,这只是一个惯例。但许多图书馆都依赖它。

关于Serializable,请参阅API文档:

类的可序列化性由实现java.io.Serializable接口。不实现此功能的类接口将不会序列化或反序列化它们的任何状态。可序列化类的所有子类型本身都是可序列化的。这个序列化接口没有方法或字段,仅用于识别可序列化的语义。

换言之,可序列化对象可以写入流,因此可以写入文件、对象数据库等。

此外,JavaBean和另一个类之间没有语法差异——如果一个类遵循标准,那么它就是JavaBean。

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


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

基本上,一个“憨豆”:

是一个可串行化的对象(即,它实现java.io.serializable,并正确执行)具有“财产”,其getter和setter只是具有特定名称的方法(例如,getFoo()是“Foo”属性的getter),并且有一个公共的零参数构造函数(因此可以随意创建并通过设置其财产进行配置)。

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

当然,为了做到这一点,班级必须遵守某些限制。其中最主要的是,所有实例字段必须要么是原始类型(int、bool等),要么是某些类的实例,也可以是可序列化的,要么标记为瞬时的,这样Java就不会试图包含它们。(这当然意味着瞬态字段将无法在流上运行。如果需要,具有瞬态字段的类应该准备好重新初始化它们。)

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


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


JavaBeans是遵循极其简单的编码约定的Java类。你所要做的就是

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


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


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

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

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

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


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

JavaBeans在整个JavaEE中被用作运行时发现和访问的通用契约。例如,JavaServerPages(JSP)使用JavaBeans作为页面之间或servlet和JSP之间的数据传输对象。Java EE的JavaBeans激活框架使用Java Beans将对MIME数据类型的支持集成到Java EE中。Java EE管理API使用JavaBeans作为在Java EE环境中管理的资源插入的基础。

关于序列化:

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

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


JavaBean的财产

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

JavaBean类必须实现Serializable或可外部化JavaBean类必须具有无参数构造函数所有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;
   }
}

根据维基百科:

类必须具有公共默认构造函数(没有参数)。这允许在编辑和激活框架内轻松实例化。根据标准命名约定,类财产必须可以使用get、set、is(可以用于布尔财产而不是get)和其他方法(所谓的访问器方法和赋值器方法)进行访问。这允许在框架内轻松地自动检查和更新bean状态,其中许多框架包括各种类型财产的自定义编辑器。setter可以有一个或多个参数。该类应该是可序列化的。(这允许应用程序和框架以独立于VM和平台的方式可靠地保存、存储和恢复bean的状态。)

有关详细信息,请单击此链接。


举例说明。

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;
    }
}

它们是可序列化的,具有零参数构造函数,并允许使用getter和setter方法访问财产。命名“Bean”是为了包含这个标准,它旨在为Java创建可重用的软件组件。根据维基百科。

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


JavaBeans是一种标准,其基本语法要求已由其他答案明确解释。

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

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


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

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

它是一个可重用的软件组件。它可以将多个对象封装到一个对象中,以便可以从多个位置访问同一个对象,这是代码易于维护的一步。


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

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

值得注意的是,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早期作为构建GUI的一部分而发明的。他们遵循的模式很容易被工具拆开,让他们创建一个财产面板,这样您就可以编辑Bean的属性。通常,Bean财产表示屏幕上的控件(想想x、y、宽度、高度、文本…)

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

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

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

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

豆类本身并不是一种健康的模式。由于它们将所有财产暴露给外部操作,因此它们本质上破坏了封装,并且在使用它们时,有一种趋势(绝非要求),即创建代码以外部操作bean,而不是在bean内创建代码(违反了“不要求对象提供其值,要求对象为您做一些事情”)。使用带有最小getter和无setter的带注释POJO更像是OO还原封装,并且具有不变性的可能性。

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


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

一旦bean被实例化,JavaBeans API(java.beans.*)就可以对其进行内省并在其上调用方法。如果没有实现接口BeanInfo或扩展BeanInfo实现的类(例如SimpleBeanInfo类)可用,自省包括使用反射(隐式自省)来研究目标bean支持的方法,然后应用简单的设计模式(指南)从这些方法中推断出支持哪些财产、事件和公共方法。如果实现接口BeanInfo(对于bean Foo,必须命名为FooBeanInfo)的类可用,则API将绕过隐式内省,并使用该类的公共方法(getPropertyDescriptor()、getMethodDescriptors()和getEventSetDescriptors(())来获取信息。如果一个扩展SimpleBeanInfo的类可用,取决于哪些SimpleBeanInfo公共方法(getPropertyDescriptor()、getMethodDescriptors()和getEventSetDescriptors(())被重写,它将使用这些被重写的方法获取信息;对于未被重写的方法,它将默认为相应的隐式内省。无论如何,bean都需要实例化,即使没有对其执行隐式内省。因此,需要公共零参数构造函数。但是,当然,Serializable或Externalizable接口不需要被识别。然而,JavaBeans规范表示,“我们也希望它对于一个只想保存其内部状态而不想考虑它的小Bean来说是“微不足道的”。”因此,所有Bean都必须实现Serializable或Externalizable接口。

总的来说,JavaBeans规范对bean的组成并不严格。“编写JavaBeans组件非常容易。你不需要特殊的工具,也不必实现任何接口。编写bean只是遵循某些编码约定。你所要做的就是让你的类看起来像一个bean——使用bean的工具将能够识别和使用你的bean。”,

公共类Trivial实现java.io.Serializable{}

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

春豆

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

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

JSF托管bean

JSF管理的bean在web容器中运行。可以使用@ManagedBean注释或应用程序配置资源文件managed-bean.xml来配置它们。JSF规范仅支持通过资源注入(而不是类型安全)进行注入。此注入不适合在构造函数上注入。在任何情况下,规范要求JSF托管bean必须具有公共零参数构造函数。此外,它还表示,“从本规范的2.3版开始,强烈使用本节中指定的托管bean工具沮丧。用于解决相同问题的更好且更紧密集成的解决方案是使用上下文和依赖注入(CDI),正如JSR-365中所规定的那样。“换句话说,应该使用CDI托管bean,它确实在类似于Spring bean的构造函数上提供了类型安全依赖注入。CDI规范采用了托管bean规范,它适用于JEE平台的所有容器,而不仅仅是web层。因此,web容器需要实现CDI规范。

托管Bean

以下是ManagedBean规范的摘录“ManagedBean是容器管理的对象,另外,也被称为缩写词“POJOs”(普通的旧Java对象)……它们可以被看作是JavaSE平台上JavaBeans组件模型的JavaEE平台增强版……读者不会错过,ManagedBeans在JavaServerFaces(JSF)技术中的同名功能中有一个先驱……本规范中定义的ManagedBean代表JSF中发现的那些的概括;特别是,ManagedBeans可以在JavaEE应用程序的任何地方使用,而不仅仅是在web模块中。例如,在基本组件模型中,ManagedBean必须提供无参数构造函数,但基于ManagedBean的规范(如CDI(JSR-299))可以放宽这一要求,并允许ManagedBean为构造函数提供更复杂的签名,只要它们遵循一些定义明确的规则。。。托管Bean不能是:最终类、抽象类或非静态内部类。与常规JavaBean组件不同,托管Bean可能不可序列化。“因此,ManagedBeans规范(也称为POJO或POJObeans)允许像CDI中那样进行扩展。

CDI豆类

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

•它不是内部类。•它是一个非抽象类,或者被注释为@Decorator。•它不实现javax.enterprise.inject.spi.Extension。•未标注@Vetoed或在标注为@Vetode的包中。•它有一个适当的构造函数,或者:该类有一个没有参数的构造函数,或该类声明了一个注释为@Inject的构造函数。

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

如果任何其他Java EE规范,如果

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

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

EJBs

EJB在EJB容器中运行。EJB规范说:“会话bean组件是托管bean。”“类必须有一个不带参数的公共构造函数,”它对会话bean和消息驱动bean都这样说。此外,它还说:“不需要会话bean类来实现SessionBean接口或Serializable接口。”。“出于与JSFbean相同的原因,EJB3依赖注入基本上是资源注入,JSFbean不支持带参数的构造函数,即通过依赖注入。然而,如果EJB容器实现了CDI,“可选:类可能有一个附加的构造函数,用Inject注释注释,”它对会话bean和消息驱动bean都这样说,因为“打包到CDI bean存档中的EJB,没有用javax.enterprise.Inject.Vetoed注释注释,被认为是启用了CDI的bean。”


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

现实世界中Beans的典型用法:

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

因此,实际上,Bean只是一种约定/标准,它期望Java对象具有某种行为(序列化),并以某种方式对其进行更改(财产的setter)。

如何使用它们,只是你的发明,但我上面列举的最常见的情况。


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

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

使类实现java.io.Serializable接口。并使用ObjectOutputStream类的writeObject()方法实现序列化。

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

实现序列化具有公共无参数构造函数所有财产都是私有的,使用公共getters和setter方法。

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


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

有效的组件体系结构应允许程序从软件构建块(在本例中为Beans),可能由不同的供应商提供,也使架构师/开发人员能够选择组件(Bean),了解其功能,并将其合并到应用程序中。

因为类/对象是像Java这样的OOP语言的基本构建块,所以它们是JavaBeans体系结构中Bean的自然竞争者。

将普通Java类转换为Javabean的过程实际上只不过是使其成为可重用和可互操作的组件。这将转化为具有以下功能的Java类:

控制向其他应用程序公开的类的财产、事件和方法。(您可以有一个BeanInfo类,它只报告外部应用程序需要的那些财产、事件和方法。)持久性(可串行化或可外部化-这也意味着没有参数构造函数,对字段使用瞬态)注册事件和生成事件的能力(例如,使用绑定和约束财产)定制器(通过GUI或提供文档来定制Bean)

为了将Java类称为Javabean,它们不需要具备上述所有能力。相反,它意味着实现上述与上下文相关的子集(例如,某个框架中的bean可能不需要自定义程序,其他一些bean可能并不需要绑定和约束的财产,等等)

为了获得上述好处,Java中几乎所有领先的框架和库都隐式地遵循JavaBeans体系结构。


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

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


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

type User struct {
  Name string
  Age int
}

var user User

user.Name = "name"
user.Age = 18

var bytes, err = json.Marshal(user)

缺少结构类型是Java的错误,开发人员发现了这种严重的不足。

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


上面重复了6或7次,说明JavaBeans没有参数构造函数要求。

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

描述JavaBeans API的规范版本(1.01)中也没有提到这一要求(https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/). 此外,本规范在以下上下文中仅2次提到“null构造函数”:“每个自定义程序都应有一个空构造函数。”“每个PropertyEditor都应有一个空构造函数。”

因此,该规范的作者似乎不知道或不愿意使用“空构造函数”这一术语,对于JavaBeans本身,仍然没有提及它。


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

软件组件

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

一个组件是:

已耦合(具有依赖项)Statefull(保存实例变量的状态)不是标准化的,它是为特定的用例而设计的(JavaEEBeans之间的主要区别)在客户端计算机中运行

Java Beans(企业bean)

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

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

来源