一直想对POJO做一个总结,POJO在开发中到底是什么?为什么会提出POJO?POJO在开发中体现在哪些地方?这其实是我一直关心的,在一开始接触Java时,其实我对这POJO的概念并不是理解很深,只停留在概念上,随着我对Java的不断深入理解,我从Spring身上看到了POJO的影子,所以想从Spring上浅谈一下我对POJO的理解,内容并不深,这里我并不想专门的谈论Spring,而是从一些基本的使用角度上浅谈POJO,也能进一步理解Spring设计理念的一些体现。
POJO,即"Plain Old Java Object"。我们可以认为POJO是一个"纯粹"的Java对象,而什么是"纯粹"的Java对象?就是以Java语言规范为基础设计的对象就是一个POJO。从而进一步我们可以理解POJO是指没有实现相关第三方接口、继承相关的第三方类的Java对象,即非侵入的Java对象。
POJO可以从以前的EJB开发模式中谈起,在Spring以前,EJB主导的开发模式中,EJB开发者需要依赖按照J2EE规范实现的J2EE应用服务器,具体实现时需要遵循一系列的接口标准,这样才能够在应用服务器的环境中得到测试和部署(特别是测试环境依赖于对制定规范接口的调用),所以在EJB规范中设计的各种类大都属于侵入式,即,他们会去实现相关的接口、继承相关的父类,他们与业务紧密相连,而不是一个简单的、纯粹的类,而Spring设计者提倡J2EE without EJB,正是基于POJO的设计思想,让我们在业务系统中设计一些“纯粹的”类,它们只是符合Java语言规范的简单Java对象,这样脱离以前EJB复杂的开发流程下,我们开发的入门、测试、应用部署都得到了简化。
比如一个简单的User类:
public class User {
private long id;
private String name;
public void setId(long id) {
this. id = id;
}
public void setName(String name) {
this. name=name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
}
上述就是一个简单的POJO,它并未与其他业务框架产生耦合,比如实现特定业务框架的接口、继承相关业务类等,它只不过是简单的按照Java语言规范定义了相关的private
属性,并提供基本的getter
、setter
对外暴露接口提供对该对象的基本操作。
为什么说POJO的设计更能简化开发?其实本质上就是我们在开发中先定义核心的POJO,比如上面的User类,它与我们的业务相关,它是关于用户数据承载的类,但我们只是简单的基于面向对象设计理念,将用户抽象为一个User类,它具有用户相关的属性描述,此时基于面向对象OO、基本的Java语言规范以及基本的开发规范(属性private、对外getter、setter)就完成了一个基本的POJO。其他人一看,它就是一个纯粹的Java对象罢了,它有基本的属性和方法。
基于上述基本的POJO的设计后,虽然它此时并不能为我们的业务提供支持,但我们现在就可以在此基础上进行不断的扩展,让它不断的适配我们的业务系统,比如现在我们的系统需要相关的身份验证、鉴权,那么我们就可以让该POJO实现Spring Security特有的UserDetail
接口,此时它就从一个普通的POJO摇身一变成为了与系统安全相关的业务类。而如果我们不是想做系统安全相关的系统设计,而是打算让它成为数据库用户表的数据承载,那么我们甚至可以不用修改它,让它作为数据库查询、插入相关的数据载体等。此时这两种应用场景的示例都是在POJO基础上进行扩展的,基于POJO简单的特点,使得我们在开发时可以在POJO基础上具有高度的扩展性,完成不同方向的设计,这就是Spring所提倡的POJO开发方式。
另一个更能说明的例子就是SpringMVC,在原本J2EE规范下进行Web开发时,我们往往会根据特定业务设计一种类型的Servlet
,而为了支持被Web容器所管理,通常我们会去继承HttpServlet
,比如:
public class FooHttpServlet extends HttpServlet {
@Override
public void init() throws ServletException {
// code
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// code
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// code
}
}
上述的FooHttpServlet
就不是一个POJO,因为它继承了特定规范的 HttpServlet
抽象类,我们可以认为这个类已经被侵入了,所以它只能用于特定的场合(Web)。
但SpringMVC设计理念中,以DispatcherServlet
为核心的MVC模式所设计的Controller,比如:
public class FooController {
public void methdA(){
// code
}
}
它就是一个POJO,因为它本身没有实现相关的接口、继承相关的类等,而如果在SpringMVC层面,我们要让这个POJO起作用,我们只需要将它通过在XML配置Bean的方式让IOC容器启动时扫描并加入到容器中即可提供服务,这就是Spring所一直倡导的POJO开发模式的具体体现之一,这种方式是相当的简洁的,因为如果它不是一个POJO,比如它还实现了相关接口、继承相关的类,那么我们在使用时还需要了解这些接口规范等,那么开发时也就有了复杂性,而简单的一个POJO,我们只需要停留在这一个层面即可,对比起来POJO的优势就体现出来的。
当然,现在实际开发中,我们并不会完全的按照POJO的设计方式,比如上面的FooController
我们很少会专门在XML中配置它,而是通过在上面注解的方式:
@Controller
public class MyController {
public void methdA(){
// code
}
}
若严格按照POJO的定义来理解,那么它此时就不是一个POJO了,但总的来说,它比起原本J2EE开发模式中使用Servlet 已经相当的简洁的,上述虽然严格上不是一个POJO,但可以认为它是在POJO的基础上进行扩展的,而Spring要做到基于POJO或以POJO为基础进行扩展的开发模式,首先要做的就是在原本特定场合(如Web)的规范下向上抽象,通过建立抽象层使得我们可以只需要在最上层通过设计简单的POJO或基于POJO扩展的对象就能完成应用功能的设计,而基于Spring的相关应用(如MVC、Security)帮助我们完成了中间层复杂的转换,其实现核心就是,将开发中面临的共性问题集中抽象,Spring对抽象层进行实现,从而为开发者提供最小程度的设计成本,也就是设计一个最简单的POJO来完成应用的开发,这就是Spring希望做的。