Appearance
为了提升代码质量、保持代码风格统一、减少沟通成本、提升团队研发效能,特对Java领域相关命名进行规范。
1. 概述
Java中常用到的命名形式共有三种:
首字母大写的大驼峰命名(UpperCamelCase)
首字母小写的小驼峰命名(lowerCamelCase)
全部大写的并用下划线分割单词(UPPER_CAMEL_UNSER_SCORE)
通常约定,类一般采用大驼峰命名,方法和局部变量使用小驼峰命名,而大写下划线命名通常是常量和枚举中使用。
类型 | 约束 | 例 |
---|---|---|
项目名 | 全部小写,多个单词用中划线分隔‘-’ | spring-cloud |
包名 | 全部小写 | com.cj.common |
类名 | 单词首字母大写 | Feature, ParserConfig, DefaultFieldDeserializer |
变量名 | 首字母小写,多个单词组成时,除首个单词,其他单词首字母都要大写 | password, userName |
常量名 | 全部大写,多个单词,用'_'分隔 | CACHE_EXPIRED_TIME |
方法 | 同变量 | read(), readObject(), getById() |
2. 包命名规范
包(Package)的作用是将功能相似或相关的类或者接口进行分组管理,便于类的定位和查找。同时,也可以使用包来避免类名的冲突和访问控制,使代码更容易维护。
通常,包命使用小写英文字母进行命名,并使用“.”进行分割,每个被分割的单元只能包含一个名词。
格式:com.cj.projectname.modulename.……
下面是一些包命名示例:
package org.springframework.boot.autoconfigure.cloud
package org.springframework.boot.util
package org.hibernate.action
package org.hibernate.cfg
package com.alibaba.druid
package com.alibaba.druid.filter
package com.alibaba.nacos.client.config
package com.ramostear.blog.web
package org.springframework.boot.autoconfigure.cloud
package org.springframework.boot.util
package org.hibernate.action
package org.hibernate.cfg
package com.alibaba.druid
package com.alibaba.druid.filter
package com.alibaba.nacos.client.config
package com.ramostear.blog.web
3. 类命名规范
类名使用大驼峰命名形式,类命通常时名词或名词短语; 接口名还可以使用形容词或形容词短语表示实现该接口的类有某种功能或能力,如Cloneable,Callable等; 测试类以它要测试的类开头,以Test结尾,如HashMapTest。
一般地,类名尽量使其保持简单和描述的完整性,类名中不要使用缩写(约定俗成的命名除外,缩写全部为大写)。
类型 | 约束 | 例 |
---|---|---|
抽象类 | Abstract 或者 Base 开头 | BaseUserService |
枚举类 | Enum 作为后缀 | GenderEnum |
工具类 | Utils作为后缀 | StringUtils |
异常类 | Exception结尾 | RuntimeException |
接口实现类 | 接口名+ Impl | UserServiceImpl |
领域模型相关 | /DO/DTO/VO/DAO | 正例:UserDAO 反例: UserDo, UserDao |
设计模式相关类 | Builder,Factory等 | 当使用到设计模式时,需要使用对应的设计模式作为后缀,如ThreadFactory |
处理特定功能的 | Handler,Predicate, Validator 表示处理器,校验器,断言,这些类工厂还有配套的方法名 | 如handle,predicate,validate |
测试类 | Test结尾 | UserServiceTest, 表示用来测试UserService类的 |
MVC分层 | Controller,Service,ServiceImpl,DAO后缀 | UserManageController,UserManageDAO |
4.1 抽象类命名规范
抽象类(Abstract Class)是一种特殊的类,其命名与普通类的命名规范相当。一般地,为了将抽象类与普通类和接口做出区别,提高抽象类的可读性,在命名抽象类时,会以“Abstract”/“Base”作为类命的前缀。
以下是Spring Framework中常见的抽象类示例:
public abstract class AbstractAspectJAdvice{
}
public abstract class AbstractSingletonProxyFactoryBean{
}
public abstract class AbstractBeanFactoryPointcutAdvisor{
}
public abstract class AbstractCachingConfiguration{
}
public abstract class AbstractContextLoaderInitializer{
}
public abstract class AbstractAspectJAdvice{
}
public abstract class AbstractSingletonProxyFactoryBean{
}
public abstract class AbstractBeanFactoryPointcutAdvisor{
}
public abstract class AbstractCachingConfiguration{
}
public abstract class AbstractContextLoaderInitializer{
}
4.2 枚举命名规范
枚举(Enum)类是一种特殊的类,其命名规范遵循普通类的命名约束条件,采用大驼峰命名法;枚举类中定义的值的名称遵循常量的命名规范。
下面是枚举的一些示例:
public enum Color{
RED,
YELLOW,
BLUE,
GREEN,
WHITE;
}
public enum PhysicalSize{
TINY,
SMALL,
MEDIUM,
LARGE,
HUGE,
GIGANTIC;
}
public enum Color{
RED,
YELLOW,
BLUE,
GREEN,
WHITE;
}
public enum PhysicalSize{
TINY,
SMALL,
MEDIUM,
LARGE,
HUGE,
GIGANTIC;
}
4.4 异常类命名规范
异常类(Exception Class)也是类的一种,但与普通类命名不同的是,异常类在命名时需要使用“Exception”作为其后缀。
下面是常见的异常类命名示例:
public class FileNotFoundException{
}
public class UserAlreadyExistException{
}
public class TransactionException{
}
public class ClassNotFoundException{
}
public class IllegalArgumentException{
}
public class IndexOutOfBoundsException{
}
public class FileNotFoundException{
}
public class UserAlreadyExistException{
}
public class TransactionException{
}
public class ClassNotFoundException{
}
public class IllegalArgumentException{
}
public class IndexOutOfBoundsException{
}
另外,在Java中还有另外一类异常类,它们属于系统异常,这一类异常类的命名使用“Error”作为其后缀,以区分Exception(编码,环境,操作等异常)。
下面是系统异常(非检查异常)的命名示例:
public abstract class VirtualMachineError{
}
public class StackOverflowError{
}
public class OutOfMemoryError{
}
public class IllegalAccessError{
}
public class NoClassDefFoundError{
}
public class NoSuchFieldError{
}
public class NoSuchMethodError{
}
public abstract class VirtualMachineError{
}
public class StackOverflowError{
}
public class OutOfMemoryError{
}
public class IllegalAccessError{
}
public class NoClassDefFoundError{
}
public class NoSuchFieldError{
}
public class NoSuchMethodError{
}
4.5 接口命名规范
首先,接口(Interface)是一种表述某一类型对象动作的特殊类;接口的名称的书写也应该符合类名书写规范,与普通类名不同的是,接口命名时可采用形容词或动词来描述接口的动作行为。
在Spring Framework标准库中,通常采用名词+动词/形容词的组合方式来命名接口,下列是Spring Framework中一些接口命名示例:
public interface AfterAdvice{
}
public interface TargetClassAware{
}
public interface ApplicationContextAware{
}
public interface MessageSourceResolvable{
}
public interface AfterAdvice{
}
public interface TargetClassAware{
}
public interface ApplicationContextAware{
}
public interface MessageSourceResolvable{
}
4.6 接口实现类
接口实现类使用“Impl作为后缀”, 下面是接口和接口实现类的书写示例:
public interface OrderService{
}
public class OrderServiceImpl implements OrderService{
}
public interface OrderService{
}
public class OrderServiceImpl implements OrderService{
}
4.7 测试类和测试方法
在项目中,测试类采用被测试业务模块名/被测试接口/被测试类+“Test”的方法进行书写,测试类中的测试函数采用“test”+用例操作_状态的组合方式进行书写, 例如:
public class UserServiceTest{
public void testFindByUsernameAndPassword(){
}
public void testUsernameExist_notExist(){
}
public void testDeleteById_isOk(){
}
}
}
public class UserServiceTest{
public void testFindByUsernameAndPassword(){
}
public void testUsernameExist_notExist(){
}
public void testDeleteById_isOk(){
}
}
}
5. 变量&常量命名
5.1 变量命名
变量(Variable)是指在程序运行中可以改变其值的量,包括成员变量和局部变量。变量命名通常以小写字母开头,如果变量名由多单词组成时,第一个单词的首字母小写,其后单词的首字母大写,俗称骆驼式命名法(也称驼峰命名法),如 computedValues,index. 变量命名时,尽量简短且能清楚的表达变量的作用,命名体现具体的业务含义即可。
变量名应简短且富于描述,变量名的选用应该易于记忆,即,能够指出其用途。尽量避免单个字符的变量名,除非是一次性的临时变量。
5.2 常量命名
一般地,常量名称采用全部大写的英文单词书写,如果常量名称由多个单词组成,则单词之间统一使用“_”进行分割,下面是常量命名示例:
public static final String LOGIN_USER_SESSION_KEY = "current_login_user";
public static final int MAX_AGE_VALUE = 120;
public static final int DEFAULT_PAGE_NO = 1;
public static final long MAX_PAGE_SIZE = 1000;
public static final boolean HAS_LICENSE = false;
public static final boolean IS_CHECKED = false;
public static final String LOGIN_USER_SESSION_KEY = "current_login_user";
public static final int MAX_AGE_VALUE = 120;
public static final int DEFAULT_PAGE_NO = 1;
public static final long MAX_PAGE_SIZE = 1000;
public static final boolean HAS_LICENSE = false;
public static final boolean IS_CHECKED = false;
5.3通用命名规则
- 尽量不要使用拼音;杜绝拼音和英文混用。 正例: BeiJing, HangZhou 反例: validateCanShu
- 命名过程中尽量不要出现特殊的字符,常量除外。
- 尽量不要和jdk或者框架中已存在的类重名,也不能使用java中的关键字命名。
- 妙用介词,如for(可以用同音的4代替), to(可用同音的2代替), from, with,of等。 如类名采用User4RedisDO,方法名getUserInfoFromRedis,convertJson2Map等。
6. 方法命名规范
方法(Method)命名采用小驼峰的形式,首字小写,往后的每个单词首字母都要大写。 和类名不同的是,方法命名一般为动词或动词短语,与参数或参数名共同组成动宾短语,即动词 + 名词。 一个好的函数名一般能通过名字直接获知该函数实现什么样的功能。
⚠️ Prefix-前缀,Suffix-后缀,Alone-单独使用
6.1 返回真伪值的方法
位置 | 单词 | 意义 | 例 |
---|---|---|---|
Prefix | is | 对象是否符合期待的状态 | isValid |
Prefix | can | 对象能否执行所期待的动作 | canRemove |
Prefix | should | 调用方执行某个命令或方法是好还是不好,应不应该,或者说推荐还是不推荐 | shouldMigrate |
Prefix | has | 对象是否持有所期待的数据和属性 | hasObservers |
Prefix | needs | 调用方是否需要执行某个命令或方法 | needsMigrate |
6.2 用来检查的方法
单词 | 意义 | 例 |
---|---|---|
ensure | 检查是否为期待的状态,不是则抛出异常或返回error code | ensureCapacity |
validate | 检查是否为正确的状态,不是则抛出异常或返回error code | validateInputs |
6.3 按需求才执行的方法
位置 | 单词 | 意义 | 例 |
---|---|---|---|
Suffix | IfNeeded | 需要的时候执行,不需要的时候什么都不做 | drawIfNeeded |
Prefix | might | 同上 | mightCreate |
Prefix | try | 尝试执行,失败时抛出异常或是返回errorcode | tryCreate |
Suffix | OrDefault | 尝试执行,失败时返回默认值 | getOrDefault |
Suffix | OrElse | 尝试执行、失败时返回实际参数中指定的值 | getOrElse |
Prefix | force | 强制尝试执行。error抛出异常或是返回值 | forceCreate, forceStop |
6.4 异步相关方法
位置 | 单词 | 意义 | 例 |
---|---|---|---|
Prefix | blocking | 线程阻塞方法 | blockingGetUser |
Suffix | InBackground | 执行在后台的线程 | doInBackground |
Suffix | Async | 异步方法 | sendAsync |
Suffix | Sync | 对应已有异步方法的同步方法 | sendSync |
Prefix or Alone | schedule | Job和Task放入队列 | schedule, scheduleJob |
Prefix or Alone | post | 同上 | postJob |
Prefix or Alone | execute 执行异步方法(注:我一般拿这个做同步方法名) | execute, executeTask | |
Prefix or Alone | start | 同上 | start, startJob |
Prefix or Alone | cancel | 停止异步方法 | cancel, cancelJob |
Prefix or Alone | stop | 同上 | stop, stopJob |
6.5 回调方法
位置 | 单词 | 意义 | 例 |
---|---|---|---|
Prefix | on | 事件发生时执行 | onCompleted |
Prefix | before | 事件发生前执行 | beforeUpdate |
Prefix | pre | 同上 | preUpdate |
Prefix | will | 同上 | willUpdate |
Prefix | after | 事件发生后执行 | afterUpdate |
Prefix | post | 同上 | postUpdate |
Prefix | did | 同上 | didUpdate |
Prefix | should | 确认事件是否可以发生时执行 | shouldUpdate |
6.6 操作对象生命周期的方法
单词 | 意义 | 例 |
---|---|---|
initialize | 初始化。也可作为延迟初始化使用 | initialize |
pause | 暂停 | onPause ,pause |
stop | 停止 | onStop,stop |
abandon | 销毁的替代 | abandon |
destroy | 同上 | destroy |
dispose | 同上 | dispose |
6.7 与集合操作相关的方法
单词 | 意义 | 例 |
---|---|---|
contains | 是否持有与指定对象相同的对象 | contains |
add | 添加 | addJob |
append | 添加 | appendJob |
insert | 插入到下标n | insertJob |
put | 添加与key对应的元素 | putJob |
remove | 移除元素 | removeJob |
enqueue | 添加到队列的最末位 | enqueueJob |
dequeue | 从队列中头部取出并移除 | dequeueJob |
push | 添加到栈头 | pushJob |
pop | 从栈头取出并移除 | popJob |
peek | 从栈头取出但不移除 | peekJob |
find | 寻找符合条件的某物 | findById |
6.8 与数据相关的方法
单词 | 意义 | 例 |
---|---|---|
create | 新创建 | createAccount |
new | 新创建 | newAccount |
from | 从既有的某物新建,或是从其他的数据新建 | fromConfig |
to | 转换 | toString |
update | 更新既有某物 | updateAccount |
load | 读取 | loadAccount |
fetch | 远程读取 | fetchAccount |
delete | 删除 | deleteAccount |
remove | 删除 | removeAccount |
save | 保存 | saveAccount |
store | 保存 | storeAccount |
commit | 保存 | commitChange |
apply | 保存或应用 | applyChange |
clear | 清除数据或是恢复到初始状态 | clearAll |
reset | 清除数据或是恢复到初始状态 | resetAll |
6.9 成对出现的动词
单词 | 意义 |
---|---|
get获取 | set 设置 |
add 增加 | remove 删除 |
create 创建 | destory 移除 |
start 启动 | stop 停止 |
open 打开 | close 关闭 |
read 读取 | write 写入 |
load 载入 | save 保存 |
create 创建 | destroy 销毁 |
begin 开始 | end 结束 |
backup 备份 | restore 恢复 |
import 导入 | export 导出 |
split 分割 | merge 合并 |
inject 注入 | extract 提取 |
attach 附着 | detach 脱离 |
bind 绑定 | separate 分离 |
view 查看 | browse 浏览 |
edit 编辑 | modify 修改 |
select 选取 | mark 标记 |
copy 复制 | paste 粘贴 |
undo 撤销 | redo 重做 |
insert 插入 | delete 移除 |
add 加入 | append 添加 |
clean 清理 | clear 清除 |
index 索引 | sort 排序 |
find 查找 | search 搜索 |
increase 增加 | decrease 减少 |
play 播放 | pause 暂停 |
launch 启动 | run 运行 |
compile 编译 | execute 执行 |
debug 调试 | trace 跟踪 |
observe 观察 | listen 监听 |
build 构建 | publish 发布 |
input 输入 | output 输出 |
encode 编码 | decode 解码 |
encrypt 加密 | decrypt 解密 |
compress 压缩 | decompress 解压缩 |
pack 打包 | unpack 解包 |
parse 解析 | emit 生成 |
connect 连接 | disconnect 断开 |
send 发送 | receive 接收 |
download 下载 | upload 上传 |
refresh 刷新 | synchronize 同步 |
update 更新 | revert 复原 |
lock 锁定 | unlock 解锁 |
check out 签出 | check in 签入 |
submit 提交 | commit 交付 |
push 推 | pull 拉 |
expand 展开 | collapse 折叠 |
begin 起始 | end 结束 |
start 开始 | finish 完成 |
enter 进入 | exit 退出 |
abort 放弃 | quit 离开 |
obsolete 废弃 | depreciate 废旧 |
collect 收集 | aggregate 聚集 |
7.其他命名规范
7.1 数组
在定义数组时,为了便于阅读,尽量保持以下的书写规范:
int[] array = new int[10];
int[] idArray ={1,2,3,4,5};
String[] nameArray = {"First","Yellow","Big"}
public List<String> getNameById(Integer[] ids){
}
public List<String> getNameById(Integer...ids){
}
int[] array = new int[10];
int[] idArray ={1,2,3,4,5};
String[] nameArray = {"First","Yellow","Big"}
public List<String> getNameById(Integer[] ids){
}
public List<String> getNameById(Integer...ids){
}
7.2 表述复数或者集合
如果一个变量用于描述多个数据时,尽量使用单词的复数形式进行书写,例如:
Collection<Order> orders;
int[] values;
List<Item> items;
Collection<Order> orders;
int[] values;
List<Item> items;
另外,如果表述的是一个Map数据,则应使用“map”作为其后缀,例如:
Map<String,User> userMap;
Map<String,List<Object>> listMap;
Map<String,User> userMap;
Map<String,List<Object>> listMap;
7.3 泛型类
在书写泛型类时,通常做以下的约定:
E表示Element,通常用在集合中;
ID用于表示对象的唯一标识符类型;
T表示Type(类型),通常指代类;
K表示Key(键),通常用于Map中;
V表示Value(值),通常用于Map中,与K结对出现;
N表示Number,通常用于表示数值类型;
?表示不确定的Java类型;
X用于表示异常;
U,S表示任意的类型。
下面时泛型类的书写示例:
public class HashSet<E> extends AbstractSet<E>{
}
public class HashMap<K,V> extends AbstractMap<K,V>{
}
public class ThreadLocal<T>{
}
public interface Functor<T,X extends Throwable>{
T val() throws X;
}
public class Container<K,V>{
private K key;
private V value;
Container(K key,V value){
this.key = key;
this.value = value;
}
}
public interface BaseRepository<T,ID>{
T findById(ID id);
void update(T t);
List<T> findByIds(ID...ids);
}
public static <T> List<T> methodName(Class<T> clz){
List<T> dataList = getByClz(clz);
return dataList;
}
public class HashSet<E> extends AbstractSet<E>{
}
public class HashMap<K,V> extends AbstractMap<K,V>{
}
public class ThreadLocal<T>{
}
public interface Functor<T,X extends Throwable>{
T val() throws X;
}
public class Container<K,V>{
private K key;
private V value;
Container(K key,V value){
this.key = key;
this.value = value;
}
}
public interface BaseRepository<T,ID>{
T findById(ID id);
void update(T t);
List<T> findByIds(ID...ids);
}
public static <T> List<T> methodName(Class<T> clz){
List<T> dataList = getByClz(clz);
return dataList;
}
8.代码注解
8.1 注解的原则
优雅的注解通常要满足三要素:
- Nothing is strange
没有注解的代码对于阅读者非常不友好,哪怕代码写的在清楚,阅读者至少从心理上会有抵触,所以一定要写注解。不仅要记录代码的逻辑,还有说清楚修改的逻辑。
- Less is more
从代码维护角度来讲,代码中的注解一定是精华中的精华。合理清晰的命名能让代码易于理解,对于逻辑简单且命名规范,能够清楚表达代码功能的代码不需要注解。
- Advance with the time
注解应该随着代码的变动而改变,注解表达的信息要与代码中完全一致。通常情况下修改代码后一定要修改注解。
8.2 注解格式
注解大体上可以分为两种,一种是javadoc注解,另一种是简单注解。javadoc注解可以生成JavaAPI为外部用户提供有效的支持。javadoc注解通常在使用IDEA等开发工具时都可以自动生成。
- 包注解
包注解在工作中往往比较特殊,通过包注解可以快速知悉当前包下代码是用来实现哪些功能,强烈建议工作中加上。包注解一般在包的根目录下,名称统一为package-info.java。
/**
* 落地也质量检测
* 1. 用来解决什么问题
* 对广告主投放的广告落地页进行性能检测,模拟不同的系统,如Android,IOS等; 模拟不同的网络:2G,3G,4G,wifi等
*
* 2. 如何实现
* 基于chrome浏览器,用chromedriver驱动浏览器,设置对应的网络,OS参数,获取到浏览器返回结果。
*
* 注意: 网络环境配置信息{@link cn.mycookies.landingpagecheck.meta.NetWorkSpeedEnum}目前使用是常规速度,可以根据实际情况进行调整
*
* @author cruder
* @time 2019/12/7 20:3 下午
*/
package cn.mycookies.landingpagecheck;
/**
* 落地也质量检测
* 1. 用来解决什么问题
* 对广告主投放的广告落地页进行性能检测,模拟不同的系统,如Android,IOS等; 模拟不同的网络:2G,3G,4G,wifi等
*
* 2. 如何实现
* 基于chrome浏览器,用chromedriver驱动浏览器,设置对应的网络,OS参数,获取到浏览器返回结果。
*
* 注意: 网络环境配置信息{@link cn.mycookies.landingpagecheck.meta.NetWorkSpeedEnum}目前使用是常规速度,可以根据实际情况进行调整
*
* @author cruder
* @time 2019/12/7 20:3 下午
*/
package cn.mycookies.landingpagecheck;
- 类注接
javadoc注解中,每个类都必须有注解。
/**
* Copyright (C), 2019-2020, Jann balabala...
*
* 类的介绍:这是一个用来做什么事情的类,有哪些功能,用到的技术.....
*
* @author 类创建者姓名 保持对齐
* @date 创建日期 保持对齐
* @version 版本号 保持对齐
*/
/**
* Copyright (C), 2019-2020, Jann balabala...
*
* 类的介绍:这是一个用来做什么事情的类,有哪些功能,用到的技术.....
*
* @author 类创建者姓名 保持对齐
* @date 创建日期 保持对齐
* @version 版本号 保持对齐
*/
- 属性注解
在每个属性前面必须加上属性注释。
/** 提示信息 */
private String userName;
/**
* 密码
*/
private String password;
/** 提示信息 */
private String userName;
/**
* 密码
*/
private String password;
- 方法注释
在每个方法前面必须加上方法注释,对于方法中的每个参数,以及返回值都要有说明。
/**
* 方法的详细说明,能干嘛,怎么实现的,注意事项...
*
* @param xxx 参数1的使用说明, 能否为null
* @return 返回结果的说明, 不同情况下会返回怎样的结果
* @throws 异常类型 注明从此类方法中抛出异常的说明
*/
/**
* 方法的详细说明,能干嘛,怎么实现的,注意事项...
*
* @param xxx 参数1的使用说明, 能否为null
* @return 返回结果的说明, 不同情况下会返回怎样的结果
* @throws 异常类型 注明从此类方法中抛出异常的说明
*/
- 构造方法注释
在每个构造方法前面必须加上注释,注释模板如下:
/**
* 构造方法的详细说明
*
* @param xxx 参数1的使用说明, 能否为null
* @throws 异常类型 注明从此类方法中抛出异常的说明
*/
/**
* 构造方法的详细说明
*
* @param xxx 参数1的使用说明, 能否为null
* @throws 异常类型 注明从此类方法中抛出异常的说明
*/
在使用注解时应该注意一下几点:
枚举类的各个属性值都要使用注解,枚举可以理解为是常量,通常不会发生改变,通常会被在多个地方引用,对枚举的修改和添加属性通常会带来很大的影响。
保持排版整洁,不要使用行尾注释;双斜杠和星号之后要用1个空格分隔。
总结
优秀的代码往往能够见名知意,无论是命名和注解,他们的目的都是为了让代码和工程师进行对话,增强代码的可读性,可维护性。
扩展:速记 Java 开发中的各种O
最后,通过一张表和图快速对Java中的BO,DTO,DAO,PO,POJO,VO之间的含义,区别以及联系进行梳理。
名称 | 使用范围 | 解释说明 |
---|---|---|
BO | 用于Service,Manager,Business等业务相关类的命名 | Business Object业务处理对象,主要作用是把业务逻辑封装成一个对象。 |
DTO | 经过加工后的PO对象,其内部属性可能增加或减少 | Data Transfer Object数据传输对象,主要用于远程调用等需要大量传输数据的地方,例如,可以将一个或多个PO类的部分或全部属性封装为DTO进行传输 |
DAO | 用于对数据库进行读写操作的类进行命名 | Data Access Object数据访问对象,主要用来封装对数据库的访问,通过DAO可以将POJO持久化为PO,也可以利用PO封装出VO和DTO |
PO | Bean,Entity等类的命名 | Persistant Object持久化对象,数据库表中的数据在Java对象中的映射状态,可以简单的理解为一个PO对象即为数据库表中的一条记录 |
POJO | POJO是DO/DTO/BO/VO的统称 | Plain Ordinary Java Object 简单Java对象,它是一个简单的普通Java对象,禁止将类命名为XxxxPOJO |
VO | 通常是视图控制层和模板引擎之间传递的数据对象 | Value Object 值对象,主要用于视图层,视图控制器将视图层所需的属性封装成一个对象,然后用一个VO对象在视图控制器和视图之间进行数据传输。 |
AO | 应用层对象 | Application Object,在Web层与Service层之间抽象的复用对象模型,很少用。 |
下面将通过一张图来理解上述几种O之间相互转换的关系: