【Java】JavaBean、POJO和EJB

Posted by 西维蜀黍 on 2018-02-23, Last Modified on 2021-09-21

1 JavaBeans

JavaBeans在1996年被Sun公司提出,并定义为 A JavaBean is reusable, platform independent component that can be manipulated visually in a builder tool.

JavaBeans是一类符合一定编写规范(满足某些约定)的可被作为重用组件的Java类。

JavaBeans 是可重用组件,通过将不同的类(Object)封装到一个类(single Object)中,这个类被称为一个 Bean。

对于一个其方法命名、构造及行为必须符合以下约定的Java类,称为一个bean

  • 所有属性为private
  • 这个类必须有一个公共的缺省构造函数(即无参数的构造函数)
  • 这个类的属性(property)可能使用 set方法 和 get方法来访问(或is方法,用于访问布尔型属性)
  • 这个类的属性可具有只读、只写或可读可写的状态
  • 这个类是可序列化的(实现了serializable接口)
  • 这个类可以将很多类封装到自己内部

例子

GUI 组件(Component) 均是理想的JavaBeans,即所有的SwingAWT类均是JavaBeans

在GUI 组件中:

  • 属性(Properties):JavaBeans的属性是一组被命名的字段,可以包括颜色(color)、标签(label)、字体(font)、字体大小(font size)、显示模式(display size),可用于描述GUI组件的外观、行为和状态
  • 方法(Methods):JavaBeans的方法与一般Java方法相同。所有的属性都通过方法来读取和修改
  • 事件(Event):JavaBeans的事件与 SWING/AWT中的事件处理(event handling)相同
  • 持久化(persistence):实现了Serializable接口使得每个JavaBeans都可以完成持久化存储

当然,我们也可以自己编写JavaBeans

PersonBean.java

public class PersonBean implements java.io.Serializable {

    /**
     * name 属性(注意大小写)
     */
    private String name = null;

    private boolean deceased = false;

    /** 无参构造器(没有参数) */
    public PersonBean() {
    }

    /**
     * name 属性的Getter方法
     */
    public String getName() {
        return name;
    }

    /**
     * name 属性的Setter方法
     * @param value
     */
    public void setName(final String value) {
        name = value;
    }

    /**
     * deceased 属性的Getter方法
     * 布尔型属性的Getter方法的不同形式(这里使用了is而非get)
     */
    public boolean isDeceased() {
        return deceased;
    }

    /**
     * deceased 属性的Setter方法
     * @param value
     */
    public void setDeceased(final boolean value) {
        deceased = value;
    }
}

TestPersonBean.java

import player.PersonBean;

/**
 * <code>TestPersonBean</code>类
 */
public class TestPersonBean {
    /**
     * PersonBean 类测试方法的main函数
     * @param ARGS
     */
    public static void main(String[] args) {
        PersonBean person = new PersonBean();

        person.setName("张三");
        person.setDeceased(false);

        // 输出: "张三[活着]"
        System.out.print(person.getName());
        System.out.println(person.isDeceased() ? " [已故]" : " [活着]");
    }
}

JSP中访问JavaBeans

JavaBeans可以被使用在JSP中,即在Servlet(相当于Controller)中根据用户通过HTTP请求传递过来的参数构造一个Beans实例(通过调用Beans实例的各种setter方法),并存储到 HttpSession中的。

在JSP页面中,可将这个Beans实例取出(从 HttpSession中),并将其属性显示在HTML页面中。

一个视频例子:Youtube - Java Beans simplified with the dynamic web programming example. using servlets, xml, jsp, html


<jsp:useBean> 标签可以在JSP中声明一个Beanjsp:useBean中的id属性用于指定这个Bean实例的名称(id值可任意设置,只要不和同一JSP文件中其他Bean实例名字相同即可),而class属性指定这个Bean的类类型。

jsp:useBean 标签主体中使用 <jsp:getProperty/> 标签来调用 getter 方法,使用 <jsp:setProperty/> 标签来调用 setter 方法:

<jsp:useBean id="Bean实例的名称" class="Bean的类类型" scope="Bean作用域">
   <jsp:setProperty name="Bean实例的名称" property="Bean实例的名称中的某属性名"  
                    value="value"/>
   <jsp:getProperty name="Bean实例的名称" property="Bean实例的名称中的某属性名"/>
   ...........
</jsp:useBean>

testPersonBean.jsp

<% // 在JSP中使用PersonBean类 %>
<jsp:useBean id="person" class="player.PersonBean" scope="page"/>
<jsp:setProperty name="person" property="*"/>

<html>
    <body>
        姓名<jsp:getProperty name="person" property="name"/><br/>
        已故与否<jsp:getProperty name="person" property="deceased"/><br/>
        <br/>
        <form name="beanTest" method="POST" action="testPersonBean.jsp">
            输入姓名<input type="text" name="name" size="50"><br/>
            选择选项
            <select name="deceased">
                <option value="false">活着</option>
                <option value="true">已故</option>
            </select>
            <input type="submit" value="测试这个JavaBean">
        </form>
    </body>
</html>

2 EJB

当初,Java为了响应满足所谓“企业级应用”的开发,具有可伸缩的性能和事务、安全机制,推出了一个叫Java Platform, Enterprise Edition (J2EE) 的框架。

针对该企业级开发对应的JavaBeans,变成了Enterprise Java Bean (EJB)。而且EJB本身比JavaBeans更复杂。

设计EJB的初衷,是希望开发者能够把精力只放在业务上,而事务管理、安全管理和线程管理等统统都交给容器(Web Server)来处理。

  • 使用**会话Bean(Session Bean)**来专注于处理业务
  • 使用**实体Bean(Entity Bean)**来和数据库中的元组(tuple)形成映射,使用开发者和数据库打交道,甚至连SQL可能都不需要写
  • 使用**消息驱动Bean(Message Driven Bean)**来与消息队列进行连接,以处理消息

很快,大家发现EJB极其笨重(在定义一个EJB时,需要增加一大堆与业务逻辑完全没有关系的代码,被迫实现一些与业务逻辑没有任何关系的接口),比如:

public class HelloWorldBean implements SessionBean{
    public  void setSessionContext(SessionContext context){
    }
    
    public void ejbCreate() throws CreateException{
    }
    
    public void ejbActivate() throws CreateException{
    }
    
    public void ejbPassivate() throws CreateException{
    }
    
    public void ejbRemove() throws CreateException{
    }
    
    // 只有这个方法包含业务逻辑,而上面实现的方法都仅仅是为了通过编译
    public String hello(){
        return "hello world";
    }
}

于是,在2000年,程序员们发起了一场叫Plain Old Java Object (POJO)的运动(POJO这个词被Martin Fowler提出),他们希望上面这个类变成这样:

public class HelloworldBean{
    public String hello(){
        return "hello world"
    }
}

因此,提出POJO的初衷,是希望这些描述实体的Java对象能够更简单(区别于复杂的JavaBeansEJB),即不需要满足任何框架中的约束。


2002年,Rod Johnson写了一本叫**《Expert One-on-One J2EE Design and Development》**的书,书中分析了Java EE的开发效率和实际性能等方面的问题,从实践和架构的角度探讨了简化开发的原则和方法(初衷是为了替代EJB,并使得Java EE开发更加简单灵活)。并以此作为方法论,实现了一个名为interface21的轻量级开发框架,interface21则为Spring框架的前身。

2014年,Spring发布1.0版本,Rod Jahnson同时推出了另一部影响深远的经典著作**《Expert one on one J2EE development withoutEJB**》。

Spring顺应了POJO的潮流,提供了一个叫Spring的容器来管理这些POJO

对于一个JavaBean来说,如果它依赖于其他的Bean,只需要声明即可。Spring容器会负责把依赖的Bean“注入进去”,这就是控制反转(IoC)

Martin flower 给这种方式起了个更好的名字,叫“依赖注入(Dependency Injections)”。

如果一个Bean 需要一些像事务、日志、安全等这样的通用的服务, 也是只需要声明即可。 Spring 容器在运行时能够动态的“植入”这些服务, 这就是依赖注入

3 Plain Old Java Object (POJO)

Plain Old Java Object (POJO)即简单的Java对象,实际上就是那些没有遵循特定框架约束,不具有任何特殊角色的Java普通对象。以将POJOJavaBeansEnterprise JavaBean (特别是 EBJ3 之前的EJB,因为 EJB3 从代码的表达性层面而言,大大减小了Enterprise JavaBean的使用复杂性)、EntityBean等区别开来。

POJO特点

  • 只有一些private属性(property),且每一个属性都包含其对应的getset方法用于获取或修改属性值
  • getset方法中不包含任何业务逻辑
  • 没有继承任何类,也没有实现任何接口(区别于JavaBeans,即POJO不需要实现serializable接口)
  • 更没有被其他框架侵入(不需要遵循任何框架的约定)

POJO对象有时也被称为Data对象,大量应用于表现现实中的对象。如果项目中使用了Hibernate框架,有一个关联的XML文件,使对象与数据库中的表对应,对象的属性与表中的字段相对应(在这个语境中,我们可以将POJO理解为简单的实体类)。

public class Student {
    private String name;
    private Integer id;

    public String getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

JavaBeans 与 POJO 的区别

POJO其实是比JavaBeans更纯净的Java简单类,POJO严格遵循简单对象的概念,而JavaBeans中可能会封装一些简单的逻辑。

POJO主要用于数据的传递,即它只能装载数据(作为存储数据的载体),但其本身不具备任何业务逻辑处理能力。

Reference