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(下)