一个 bean is 一个 Java 类,其方法名称遵循 properties、methods 和 events 的 JavaBean 准则(也称为设计模式)。因此,任何不属于属性定义的 bean 类的公共方法都是 bean 方法。最低限度,一个 Java 类,即使有一个属性作为唯一成员(当然,需要公共 getter 和 setter),一个公共方法作为唯一成员,或者只有一个公共事件侦听器注册方法,也是一个 Java bean。此外,该属性可以是只读属性(具有 getter 方法但没有 setter)或只写属性(仅具有 setter 方法)。 Java bean 需要是一个公共类才能对任何 beanbox 工具或容器可见。容器必须能够实例化它;因此,它也应该有一个公共构造函数。 JavaBeans specification 不需要 bean 有一个公共的零参数构造函数,显式的或默认的,以便容器实例化它。如果您可以提供包含序列化实例的文件(扩展名为 .ser),那么 beanbox 工具可以使用该文件来实例化原型 bean。否则,bean 将需要一个公共的零参数构造函数,无论是显式的还是默认的。
一旦 bean 被实例化,JavaBean API (java.beans.*) 就可以对它进行内省并调用它的方法。如果没有实现接口 BeanInfo 或扩展 BeanInfo 实现的类 SimpleBeanInfo 类可用,则自省涉及使用反射(隐式自省)来研究目标 bean 支持的方法,然后应用简单的设计模式(指南)从这些方法支持哪些属性、事件和公共方法。如果实现接口 BeanInfo 的类(对于 bean Foo,它必须命名为 FooBeanInfo)可用,API 绕过隐式自省并使用该类的公共方法(getPropertyDescriptor()、getMethodDescriptors()、getEventSetDescriptors())来获取信息。如果扩展 SimpleBeanInfo 的类可用,取决于 SimpleBeanInfo 公共方法(getPropertyDescriptor()、getMethodDescriptors()、getEventSetDescriptors())中的哪一个被覆盖,它将使用这些被覆盖的方法来获取信息;对于未被覆盖的方法,它将默认为相应的隐式内省。一个 bean 无论如何都需要被实例化,即使它没有进行隐式自省。因此,公共零参数构造函数的要求。但是,当然,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 是上述 Java SE 版本 (JavaBeans) 的 Java EE 版本。这些描述进一步说明了上述基本思想。
春豆
比如说,一个 bean 构造函数有一些参数。假设有些是简单类型。容器可能不知道要为它们分配什么值;即使是这样,生成的实例也可能无法重用。只有当用户可以像在 Spring bean 中那样通过注解或 xml 配置文件进行配置(指定值)时,它才有意义。并假设某些参数是类或接口类型。同样,容器可能不知道要为其分配什么值。只有当用户可以通过注解或 xml 配置文件进行配置(指定特定对象)时,它才有意义。然而,即使在 Spring(通过 xml 配置文件)中,将特定对象(带有字符串名称)分配给构造函数参数(构造函数参数的属性或元素)也不是类型安全的;它基本上类似于资源注入。引用其他 Spring bean(称为协作者;通过构造函数参数元素中的元素)基本上是依赖注入,因此是类型安全的。显然,一个依赖项(collaborator bean)可能有一个带有注入参数的构造函数;那些注入的依赖项可能有一个带参数的构造函数等等。在这种情况下,最终,您将需要一些 bean 类(例如,MyBean.class),容器可以通过简单地调用 new MyBean() 来实例化它们,然后它才能通过构造函数上的依赖注入构造其他协作 bean——因此,需要bean 具有公共的零参数构造函数。假设,如果容器不支持依赖注入和/或不允许像 Spring 中那样通过一些注释或 xml 配置文件将简单类型的值分配给构造函数,则 bean 构造函数不应该有参数。即使是 Spring bean 应用程序也需要一些 bean 来具有公共的零参数构造函数(例如,在 Spring 应用程序没有只有简单类型作为构造函数参数的 bean 的场景中)。
JSF 托管 Bean
JSF 托管 bean 在 Web 容器中运行。它们可以使用@ManagedBean 注解或应用程序配置资源文件 managed-bean.xml 进行配置。但是,它仅支持通过资源注入(非类型安全)进行注入;不适合在构造函数上注入。 JSF spec 要求托管 bean 必须具有公共零参数构造函数。此外,它还说,“从本规范的 2.3 版开始,强烈使用本节中指定的托管 bean 设施
灰心。解决相同问题的更好、更紧密集成的解决方案是使用 JSR-365 中指定的上下文和依赖注入 (CDI)。”换句话说,要使用的 CDI 托管 bean,它为类似的构造函数提供类型安全的依赖注入到Spring bean。CDI规范采用Managed Beans规范,适用于JEE平台的所有容器,而不仅仅是web层。因此,web容器需要实现CDI规范。
托管 Bean
这是Managed Bean specification 的摘录
“ Managed Beans 是具有最低要求的容器管理对象,
也称为首字母缩略词“POJO”(普通旧 Java 对象)……它们可以被视为 Java SE 平台上的 JavaBeans 组件模型的 Java EE 平台增强版本……。读者不会错过 Managed Beans 在 JavaServer Faces (JSF) 技术中发现的同名设施中的前身……本规范中定义的 Managed Beans 代表了 JSF 中的泛化;特别是,托管 Bean 可以在 Java EE 应用程序的任何地方使用,而不仅仅是在 Web 模块中。例如,在基本组件模型中,Managed Beans 必须提供无参数的构造函数,但建立在 Managed Beans 上的规范,例如 CDI (JSR-299),可以放宽该要求,并允许 Managed Beans 为构造函数提供更多复杂的签名,只要它们遵循一些明确定义的规则……托管 Bean 不能是:最终类、抽象类、非静态内部类。与常规 JavaBean 组件不同,托管 Bean 可能无法序列化。”
因此,托管 Bean(也称为 POJO 或 POJO bean)的规范允许在 CDI 中进行扩展。
CDI 豆
The CDI specification 将托管 bean 重新定义为:
在 Java EE 中运行时,如果满足要求,顶级 Java 类就是托管 bean:
• 它不是内部类。
• 它是一个非抽象类,或者被注释为@Decorator。
• 它没有实现javax.enterprise.inject.spi.Extension。
• 它没有注解@Vetoed 或在一个包中没有注解@Vetoed。
• 它有一个适当的构造函数,或者:类有一个没有参数的构造函数,或者类声明了一个带有@Inject 注释的构造函数。
所有满足这些条件的 Java 类都是托管 bean,因此没有特殊声明
需要定义托管 bean。 或者
如果它被任何定义为托管 bean
其他 Java EE 规范和 if
• 未使用 EJB 组件定义注释进行注释或声明为 EJB bean 类
在 ejb-jar.xml 中。
与 Spring bean 不同,它不支持具有简单类型的构造函数,如果它支持使用 xml 配置文件(如 Spring 或任何注释)进行配置,这可能是可能的。
EJB
EJB 在 EJB 容器中运行。它的specification 说:“会话 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豆子。”