POJO

软件工程里的POJO（plain old Java object)，也称为普通老式Java物件、纯Java物件、一般Java物件，是没有受特殊限制的一般Java物件，这是马丁·福勒（Martin Fowler）、Rebecca Parsons和Josh MacKenzie在2000年9月时所提出。

我们一直很疑惑为何人们很抗拒在其系统中使用一般的物件，结论是这类物件缺少了有趣的名字。因此我们就取了名字，如今就很受欢迎…

“POJO”一词一开始是指不依循任何主流Java物件模型、约定或框架的Java物件，和复杂的物件模型相对。

此一词语开启了一连串首字母缩略字，针对不使用先进技术的构造建立返璞词。

- JavaScript里的“普通老式JavaScript物件”（Plain old JavaScript object）
- Ruby里的“普通老式Ruby物件”（Plain old Ruby object，简称PORO）
- Perl里的“普通老式文件”（Plain old Documentation，简称pod）
- .NET框架里的“一般CLR物件”（Plain old CLR object，简称POCO）。
- PHP里的“普通老式PHP物件”（Plain old PHP object，简称POPO。
- 电话学里的“普通老式电话服务”（Plain old telephone service，简称POTS）

## 定义

理想上，POJO是一种只受Java语言规范所限制，此外不受其他限制的Java物件，因此，POJO不应：

- 继承预定义的类型，像是

```java
import javax.servlet.http.HttpServlet;

public class Foo extends HttpServlet { 
    // ...
}
```

- 实现预定义的界面，像是

```java
import javax.ejb.EntityBean;

public class Bar implements EntityBean {
    // ...
}
```

- 包括预定义的Java注解（annotations），像是

```java
import javax.persistence.Entity;

@Entity
public class Baz {
    // ...
}
```

不过，因为技术问题（例如要让持久化正常运作）和其他原因，许多宣称是POJO相容的软件产品或是框架仍需要用到一些预定义的注解。

POJO的概念是若物件（其实是类别）在加入注解之前是POJO，在移除注解后仍可以视为是POJO。POJO的基本概念是：没有特殊的特征（例如实现特定界面），因此不是“特殊Java物件”（Specialized Java Object）。

## 不同环境下的定义

### JavaBeans

JavaBeans是支援序列化，具有无参构造器，提供getter方法和setter方法存取物件的POJO。因为此命名规则，可以对任意JavaBeans的属性进行简单的宣告式参考。使用这类宣告式参考的程式码不需知道有关JavaBean类型的任何资讯，JavaBean可以用在许多的框架中，框架不需知道JavaBeans的实际型态。

若要完全实现JavaBeans规范，必须实现序列化界面，因此会稍微打破POJO的规定。因为序列化是标记界面，不需实现任何方法，在程式码上的负担很小。

以下是JavaServer Faces（JSF）元件和POJO属性双方绑定的例子：

```xml
<h:inputText value="#{MyBean.someProperty}"/>
```

POJO的定义如下：

```java
public class MyBean {
    private String someProperty;

    public String getSomeProperty() {
         return someProperty;
    }

    public void setSomeProperty(String someProperty) {
        this.someProperty = someProperty;
    }
}
```

因为JavaBean的命名原则，单一的`someProperty`参考可以自动翻译成取值的`getSomeProperty()`方法（或性质是布林，则是`isSomeProperty()`方法），以及设定值的`setSomeProperty(String)`方法。

Project Lombok函式库可以动态改变程式码，在不用写这些程式码的情形下进行整合。以下的程式码会创建相同的JavaBean，再加上空的创建子：

```java
@NoArgsConstructor
public class MyBean {
    @Getter 
    @Setter
    private String someProperty;
}
```

其他这类命名约定的函式库或是框架会直接产生程式，可减少重复代码（Boilerplate code），也减少了错误的出现率以及维护成本。

### 透明地增加服务

随着使用POJO的设计越来越普遍，已出现了为POJO提供所有功能，并且可以选择实际需要哪些功能领域的框架。在此模型下，程式设计者创建的就只有POJO。此POJO只专注在业务逻辑，不依赖（企业级）框架。面向切面的程序设计（AOP）框架透明地加入横切关注点，像是持久性（Persistence）、事务处理、安全性等。

Spring Framework是很早期实现此概念的框架，也是推广此模型的推进者之一。

以下是一些这类的例子：

- Enterprise JavaBeans（EJB）
- Java持久化API（JPA，包括Hibernate）
- CDI（Java EE平台的上下文和依赖入）

以下的例子是一个全功能的EJB bean，说明EJB3如何善用POJO模型的特点：

```java
public class HelloWorldService {

    public String sayHello() {
        return "Hello, world!";
    }
}
```

在以上的范例中，程式码没有延伸任何EJB的类别，或是实现任何EJB的界面，也不需要包括EJB的注解。程式开发者会宣告外部的XML档，说明哪些EJB服务需加在其中：

```xml
<enterprise-beans>
    <session>
        <ejb-name>helloWorld</ejb-name>
        <ejb-class>com.example.HelloWorldService</ejb-class>
        <session-type>stateless</session-type>
    </session>
</enterprise-beans>
```

在实务上，有些人会觉得Java注解比较优雅轻巧，认为XML冗长、丑陋，不容易维护，不过也有人比较在意Java注 解对POJO模型的污染。

因此，许多框架（像Spring、EJB和JPA）提供可以不用XML的替代作法，可以不加入XML，改用注解代替。以下程式也是同一个EJB bean，但加入了注解，此例中就不需要XML档了：

```java
@Stateless
public class HelloWorldService {

    public String sayHello() {
        return "Hello, world!";
    }
}
```

因为有加入注解，此程式已不是真正的纯POJO，不过注解只是被动性的元资料，和侵入式的延伸类别和实现界面来说，注解的缺点要少很多。此程式开发模型仍很像纯POJO模型。

## 相关首字母缩略字

### POJI

POJI（A Plain old Java Interface）是一种基本的Java界面，适用在不允许更复杂Java界面的应用。