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介面的應用。