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
,即所有的 Swing
和 AWT
类均是 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 页面中。
<jsp:useBean>
标签可以在 JSP 中声明一个 Bean
。jsp: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 对象能够更简单(区别于复杂的 JavaBeans
、EJB
),即不需要满足任何框架中的约束。
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 普通对象。以将 POJO
和 JavaBeans
、Enterprise JavaBean
(特别是 EBJ3 之前的 EJB,因为 EJB3 从代码的表达性层面而言,大大减小了 Enterprise JavaBean 的使用复杂性)、EntityBean
等区别开来。
POJO 特点
- 只有一些 private 属性(property),且每一个属性都包含其对应的
get
、set
方法用于获取或修改属性值 get
、set
方法中不包含任何业务逻辑- 没有继承任何类,也没有实现任何接口(区别于
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
- WikiPedia - JavaBeans
- WikiPedia - POJO
- Introduction to JavaBeans and its components
- Difference between DTO, VO, POJO, JavaBeans?
- Java 帝国之 Java bean(下)