规范化JavaBean

2024-08-21 03:36
文章标签 java bean 规范化

本文主要是介绍规范化JavaBean,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Java Bean 是一个很常见的概念,简单来说就是一个 Java 类,其中的内容就是各种属性,以及各个属性的
getter/setter 。例如:

class Student {private String name;private int age;public String getName() {return this.name;}public void setName(String name) {this.name = name;}public int setAge() {return this.age;}public void setAge(int age) {this.age = age;}
}

除了 Java Bean 这样的概念之外还有很多类似和相关的概念,《码出高效——阿里巴巴Java开发手册》中就还有
DO、DTO、VO 的概念,另外,在更高级的建模领域还有 POJO、Entity、Value Object 的概念。
大概念上,上面的各种 O 都是 Java Bean 的具体情况,或者说是更细化的情况。在高级的程序员手里,实际上直接
去使用 Java Bean 的情况并不多,更多的情况是在不同地方使用不同的 O 。
在本片笔记中,我们就来看下各种 O 的概念、使用场景以及之间的异同。当然,实际上还不止上面这些 O,我们仅
介绍最常见的几种 Java Bean 。

1. DO / PO

DO,Database Object 数据库对象。由于单词  do 在 Java 中是关键字(do-while 循环),所以在有些地方会避免
使用 DO 这个称呼,转而叫它 PO,Persistence Object 持久化对象。我个人也倾向于叫它 PO 。
无论是赤裸裸地叫数据库对象,还是委婉地叫持久化对象,很显然,这个 O 的概念一定是和数据库有关系的。
简单来说,一个 DO 类是和一个数据库中的表一一对应的 。它也是我们最常见的一种 Java Bean 。无论我们的项目
的持久层框架使用的是 Mybatis 还是 JPA/Hibernate,我们的项目中一定会有 DO / PO 的身影。
理论上来说,不考虑故意不对外暴露的情况,你有多少张表,你就会有多少个 DO 类;你的表有多少个字段,你的
DO 类就会有多少个属性;你的表的字段是什么类型,你的 DO 类的属性就是对应的什么类型。

2. DTO

DTO,Data Transfer Object 数据传输对象。它是用于 Service 层的。
Service 层调用 DAO 层时,DAO 层返回的时 DO/PO 对象,这个大家都能想到,相信大家平时的代码中也是这么写
的。但是 Controller 调用 Service 层,或者 Service 调另一个 Service 时返回的则是 DTO 对象。
为什么 Service 层不直接返回 DO/PO 对象,而又要再弄出一个 DTO 对象呢?原因有二。
1. 如果 Service 层直接返回了 DO/PO 对象,那么就会对外暴露你的数据库的表结构。
有时候,你返回的只是部分数据(数据库中的数据的部分字段),这样的话,返回 DO/PO 对象即有风险又没有
必要。
这样的话,你可以重新定义一个 DTO 类,这个类中只包含你有必要返回的那些字段,这样,调用 Service 的人
就无法知道数据库中除了 DTO 中定义的字段之外还有什么字段。
2. 简化数据的关系。
对于数据库中有一对多的情况,例如,你的数据库中有学生表和班主任表,学生和班主任是一对多的关系。那
么,你的学生类肯定是这样定义的。

class StudentPO {private String name;private int age;...private TeacherPO teacher;
}

如果你要查询一个学生的信息,并且要【顺带】查出它的班主任的信息,那么你在获得这个学生信息之后打印他的老
师的信息时,你使用学生对象的代码肯定是这样的:

System.out.println(tom.getName());
System.out.println(tom.getAge());
System.out.println(tom.getTeacher().getName());
System.out.println(tom.getTeacher().getPhone());

对于 DO/PO 对象,你需要【说】:学生的老师的名字,学生的老师的电话。通过,重定义一个 DTO 对象,你完全可以写出这样的代码:

class StudentDTO {private String name;private int age;private String teacherName;private String teacherPhone;
}

使用 DTO 的代码就可以是这样的:

System.out.println(tom.getName());
System.out.println(tom.getAge());
System.out.println(tom.getTeacherName());
System.out.println(tom.getTeacherPhone());

需要注意的是,如果你的 Service 层中多了 DTO 的定义,那么你的 Service 的职责中就多了一项:将 DAO 层返回的 DO/PO 对象转换成 DTO 对象。

3. VO

实际上 VO 对象相较而言比 DO / PO / DTO 对象要少见一些。大多数情况下,需要使用 VO 对象时,可能直接就使用了 DTO 对象了。不会再额外多定义一个类。

VO,View Object 从名字上看,它适合视图层有关的。
VO 对象面对的情况和 DTO 对象的情况类是。Controller 在调用 Service 层获得 Service 返回的 DTO 对象后,需要
将 DTO 对象转换成 VO 对象,再在 JSP 页面上展示,或者以 JSON 数据返回。
那么,问题来了:为什么需要 VO 对象,多定义一个类,而不是直接利用 DTO ,甚至是 DO / PO 对象?
不直接使用 DO / PO 对象的原因在上个章节这样已经介绍过。不直接使用 DTO 对象的原因是,DTO、DO/PO 对象中存的是【纯粹的数据】而当把数据展示在页面上时,可能需要对它进行【美化】。
什么意思呢?以 性别 为例,在数据库中人的性别大多数情况加就是用 0、1、2 这样的数值代表男、女、未知。那么,在你的 DTO、DO/PO 类中 性别 的类型就是一个简单的  int 类型。
但是在页面显示上你不可能直接显示  性别:0 、 性别:1 ,你需要将 0 和 1【美化成】男/女、先生/小姐、帅哥/美女等等个性化的内容。也即是说,至少你的 性别 要是一个字符串。
所以,Controller 要将 DTO 对象转换成 VO 对象再返回给页面或者是前端。这里就有一个转换的工作要做。

不过,上面所说的【美化】的工作其实可以转交给前端/请求方来做,没必要让 Java 后台来做这个和业务逻辑并没有太大关系的工作。因此 VO 对象其实比较少见,通常 Controller 层获得 Service 层获得到 DTO 后就返回DTO 对象,让前端/请求方自己把 0、1 【美化成】它想要显示的效果。此时,你需要在文档中和前端/调用方约定好 0、1 谁表示男,谁表示女。

4. POJO

POJO,Plain Old Java Object,很多地方都将 POJO 等同于 Java Bean,实际上 POJO 的概念要比 Java Bean 高级。
那么什么样的 Java Bean 算是一个 POJO ?
简单来说,一个 POJO 的 Java Bean 中会包含业务逻辑。这句话要是落实到代码上,那就是你的 Java Bean 除了属性的 getter / setter 方法之外还有别的(大量的)其它的方法。

例如,你定义一个钱包类:

class Wallet {private double money;...
}

通常,我们可能只是很简单地将钱包 Wallet 类定义成这个样子,当我们的需要判断钱包中的钱是否够用时,我们是自己去【亲自写】类似这样的代码:

if (wallet.getMoney() >= xxx) {// 钱够用,怎么怎么着
} else {// 钱不够用,怎么怎么着
}

但是如果是将 Wallet 定义为 POJO 的话,那么 Wallet 的设计思路要发生变化:将【判断钱包中钱是否够用】的代码移入到 Wallet 类中,即,由 Wallet 类自己去判断钱够不够用。代码如下:

class Wallet {private double money;...public boolean isEnough(double money) {return this.money >=  money;}
}

而你再使用它的时候,就只需要调用这个方法,获取结果,而不用自己去编写判断逻辑:

if (wallet.isEnough(xxx)) {// 钱够用,怎么怎么着
} else {// 钱不够用,怎么怎么着
}

概念上相当于,你不需要亲自去知道钱包中具体有多少钱,在你需要钱的时候你只需要去【问】钱包:我要 xxx 钱,你里面够不够这个数?
表面上来看,好像只是代码是在【这里】还是在【那里】的【小】问题,但是实际上这是一个类的设计思路的转变。而这个设计思路则是 DDD 建模的理论基础之一。
当然考虑到国内的普通的中小型项目极少用到 DDD 这么高级的建模方式,所以 POJO(以及基于这个概念的 Entity和 Value Object)实际上是很少见的。

你看到的叫 POJO 的类 99.99% 都是叫错了名字。POJO 类在有些地方也被叫做 Domain 类。

5. Entity 和 Value Object

简单说,Entity 和 Value Object 是 POJO 的两种具体情况。如果 POJO 类中有起 唯一性标识 作用的属性,那么这个POJO 类就是一个 Entity 类;反之则是 Value Object。
注意,此 VO(Value Object)非彼 VO(View Object),不要搞混淆了。
仍以上述的钱包 Wallet 类为例: 

如果它是 Entity,那么它应该是这样的:

class Wallet {private int id; // 唯一性标识...
}

强调一点,并不是说有唯一性标识就一定是 Entity,首先它必须是 POJO。也即是说,这个类中要有业务逻辑方法,
不能净是些 getter/setter 这种没营养的方法。

另外,这个属性名既非必须是 int ,也非必须叫 id。无论是什么类型什么名字,这个属性是起到了唯一性标识的作用,那都行。
如果它是 Value Object,那么它里面就没有这个 id 属性。

至于什么时候用 Entity,什么时候用 Value Object 我们这里就不展开说了,毕竟非 DDD 建模的项目中用不上它们。

这篇关于规范化JavaBean的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092003

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定