前提

在上一章我们提到了并且解决了几只拦路虎,承上启下,下面我们一起来实现一款数据生成器。

对外API

/**
* @description: 本地数据生成API
* @author: peter
* @create: 2020-10-02 15:09
**/
public class FastData<T> {
private T o;
private DataFactory dataFactory = DataFactory.getDataFactory(); //数据工厂 /**
* 生成单个对象
* @param clazz 欲生成的对象类型
* @return Data 生成的数据
*/
public T build(Class clazz){
try {
o = (T)clazz.newInstance();
}catch (Exception e) {
e.printStackTrace();
}
Object entity = dataFactory.build(o);
return (T)entity;
} /**
* 生成多个对象
* @param claszz 欲生成的对象类型
* @param size 欲生成数量
* @return 生成的对象数据集合
*/
public List<T> builds(Class claszz,int size){
List<T> resultList = new ArrayList<T>();
for(int i = 0; i < size; i++){
resultList.add(build(claszz));
}
return resultList;
}
}

两个方法:build(Class clazz) ,builds(Class claszz,int size)

我们来对build方法进行分析,在FastData类中,我们定义了一个泛型的对象o, 此对象的存在格外重要,在build方法中,o = (T)clazz.newInstance() 给此对象赋值一个实例,意义是为了后续能够反射出泛型对象内的属性,交由DataFactory数据工厂进行构建,dataFactory.build(o) 将返回一个已经设置了对应属性值的Object, 此Object实际上是泛型对象的装箱结果,所以 return (T)entity 此处在拆箱成泛型T,没有任何问题。

DataFactory 数据工厂

/**
* @description: 数据工厂
* @author: peter
* @create: 2020-10-02 15:13
**/
public class DataFactory {
private static DataFactory dataFactory = new DataFactory();
private ValueGeneration valueGeneration = new ValueGeneration(); //值生成器
private DataFactory(){ } public static DataFactory getDataFactory(){
return dataFactory;
} /**
* 构建数据对象
* @param o 实例类型
* @return 生成后的对象
*/
public Object build(Object o){
Object entity = null;
try {
entity = o.getClass().newInstance();//创建一个新对象
Map<String, Field> fieldMap = ObjectUtil.getFields(o);//获取对象的属性
for(String fieldName : fieldMap.keySet()){
Object value = valueGeneration.generation(fieldMap.get(fieldName).getType(),fieldMap.get(fieldName)); //生成对应类型的值
fieldMap.get(fieldName).set(entity,value);//把值设置到新对象
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} return entity; //返回新对象
} }
本类其他地方都很明了,但是有个地方需要说明一下,可能有的朋友会不解,valueGeneration.generation(fieldMap.get(fieldName).getType(),fieldMap.get(fieldName)) 
此处将fieldMap.get(fieldName)传到valueGeneration,为何还要传fieldMap.get(fieldName).getType(),这不是多次一举吗?其实不然,这里跟架构设计有关系,后续说明。

ObjectUtil 对象工具

/**
* @description: 对象工具
* @author: peter
* @create: 2020-10-02 15:14
**/
public class ObjectUtil {
//是否开启缓存
private static boolean isCache = Boolean.valueOf(PropertiesUtil.getValue("true","com.config.cache")); /**
* 属性Map
* @param o 欲反射的对象
* @return 对象的属性Map<属性名,属性>
*/
public static Map<String, Field> getFields(Object o){
Map<String,Field> fieldMap = null;
if(isCache){//是否开启缓存
//是否存在缓存
if(LocalCache.fieldMapBuffer.get(o.getClass().getName()) != null){
//返回缓存中的Map
return LocalCache.fieldMapBuffer.get(o.getClass().getName());
}else{
//反射
fieldMap = reflectionObject(o);
//添加到缓存
LocalCache.fieldMapBuffer.put(o.getClass().getName(),fieldMap);
}
}else{
fieldMap = reflectionObject(o);//反射
}
return fieldMap;
} private static Map<String,Field> reflectionObject(Object o){
Map<String,Field> fieldMap = new HashMap<String, Field>();
Field[] fields = o.getClass().getDeclaredFields();
for(Field field : fields){
fieldMap.put(field.getName(),field);
}
return fieldMap;
}
}

反射会比较消耗资源,此处做一个缓存机制,小工具也用不上Redis之类的专业内存库,自己写个Map做缓存,且使用者也应该只有极少数会在程序执行过程中更改类的属性列表,毕竟这不是一件简单的事情。

LocalCache 本地缓存

/**
* @description: Cache
* @author: peter
* @create: 2020-10-03 17:49
**/
public class LocalCache {
//序列缓存
public static Map<String,Integer> sequenceBuffer = new HashMap<String, Integer>();
//对象属性缓存
public static Map<String, Map<String, Field>> fieldMapBuffer = new HashMap<String, Map<String, Field>>();
}

此类中的序列缓存后续说明,有大用处。

在ObjectUtil中,还存在 PropertiesUtil.getValue("true","com.config.cache") 这样一句代码,此类内容如下:

PropertiesUtil 配置工具

/**
* @description: Properties 配置工具
* @author: peter
* @create: 2020-10-02 16:22
**/
public class PropertiesUtil {
private static PropertiesScan propertiesScan = PropertiesScan.getPropertiesScan(); /**
* 获取配置的值
* @param defalut 默认值
* @param propertiesKey key
* @return 配置值
*/
public static String getValue(String defalut,String propertiesKey){
String result = defalut;
if(null != propertiesScan.getValue(propertiesKey)){
result = propertiesScan.getValue(propertiesKey).toString();
}
return result;
} public static int getValueByInt(int defalut ,String propertiesKey){
int result = defalut;
if(null != propertiesScan.getValue(propertiesKey)){
result = Integer.parseInt(propertiesScan.getValue(propertiesKey).toString());
}
return result;
}
}

PropertiesScan

/**
* @description: 配置扫描
* @author: peter
* @create: 2020-10-01 17:54
**/
public class PropertiesScan {
private static PropertiesScan propertiesScan = new PropertiesScan();
private static String propertiesPath = null;
private static Properties properties = null;
private PropertiesScan(){ } public static PropertiesScan getPropertiesScan(){
propertiesScan.load();
return propertiesScan;
} private void load(){
properties = new Properties();
try {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("jfd.properties");
properties.load(inputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public Object getValue(String key){
return properties.get(key);
} }

以上均为后续的数据生成做准备,为了各位更好的观看,此篇到此为止,下一章简述数据生成部分,填上之前埋下的2个坑。精彩继续。

如何从0到1的构建一款Java数据生成器-第二章的更多相关文章

  1. 如何从0到1的构建一款Java数据生成器-第一章

    前提 某天晚上老夫在神游时,想起白天公司同事说起的问题,这老表抱怨使用mysql生成大批的随机测试数据太过麻烦,问大家有没有好的工具推荐,老夫对这种事情当然不关心,毕竟我也不知道. 秉承着不懂就要问, ...

  2. Laxcus大数据管理系统2.0(5)- 第二章 数据组织

    第二章 数据组织 在数据的组织结构设计上,Laxcus严格遵循数据和数据描述分离的原则,这个理念与关系数据库完全一致.在此基础上,为了保证大规模数据存取和计算的需要,我们设计了大量新的数据处理技术.同 ...

  3. 面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序

    面向 Java 开发人员的 Ajax: 构建动态的 Java 应用程序 Ajax 为更好的 Web 应用程序铺平了道路 在 Web 应用程序开发中,页面重载循环是最大的一个使用障碍,对于 Java™ ...

  4. 三、使用Maven构建简单的java项目

    前边,我刚搭建了Maven环境,还有给大家推荐了学习资源,这个小节,我们来就来,,简单的玩玩maven. 1.所需工具: 1.Eclipse     2.apache-maven-3.3.9   3. ...

  5. Ant构建与部署Java项目---入门

    原文地址:http://tech.it168.com/j/2007-11-09/200711091344781.shtml Ant是一个Apache基金会下的跨平台的构件工具,它可以实现项目的自动构建 ...

  6. 【原创】构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施

    原文:[原创]构建高性能ASP.NET站点 第六章-性能瓶颈诊断与初步调优(下前篇)-简单的优化措施 构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施 前言:本篇 ...

  7. 【原创】构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测CLR性能

    原文:[原创]构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)-托管资源优化-监测CLR性能 构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测C ...

  8. 微信小程序教学第二章:小程序中级实战教程之预备篇 - 项目结构设计 |基于最新版1.0开发者工具

    iKcamp官网:http://www.ikcamp.com 访问官网更快阅读全部免费分享课程:<iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享>. ...

  9. Gradle入门(3):构建第一个Java项目

    Gradle插件通过引入特定领域的约定和任务来构建你的项目.Java插件是Gradle自身装载的一个插件.Java插件提供的基本功能远比源代码编译和打包多.它为你的项目建立了一个标准的项目布局,并确保 ...

随机推荐

  1. 20190916-01linux文件与目录结构 000 001

    1./bin 是Binary的缩写,这个目录存放着最经常使用的命令 2./sbin s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序 3./home 存放普通用户的主目录,在 ...

  2. MySQL中存储json格式数据

    1.1.1. JSON类型数据存储 新建表 create table json_user ( uid int auto_increment, data json, primary key(uid) ) ...

  3. CSS 简介,学习 CSS 必看

    CSS 表示的是层叠样式表,学习 CSS 之前我们必须要掌握 HTML 和 XHTML 概述 CSS 指层叠样式表 (Cascading Style Sheets) 样式定义如何显示 HTML 元素 ...

  4. Django设置前端背景图片

    设置 setting.py 文件 STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static&qu ...

  5. elasticsearch 索引清理脚本及常用命令

    elastic索引日志清理不及时,很容易产生磁盘紧张,官网给出curl -k -XDELETE可以清理不需要的索引日志. 清理脚本 #!/bin/bash #Author: 648403020@qq. ...

  6. java之死锁

    转载自 https://www.cnblogs.com/xiaoxi/p/8311034.html 一.死锁的定义 多线程以及多进程改善了系统资源的利用率并提高了系统 的处理能力.然而,并发执行也带来 ...

  7. ribbon源码(6) Server

    Server 代表一个服务器信息. 内部有服务器地址(host).服务器端口(port).服务器dc(zone).是否存活标志(isAliveFlag).请求协议(scheme).是否可以提供服务(r ...

  8. RabbitMQ Server安装及显示管理界面Installing on Windows

    接上一篇文章,继续讲解 文件很小, 1.下载路径:http://www.rabbitmq.com/download.html 2.运行rabbitmq-server-3.6.5.exe,选择要安装的目 ...

  9. PostGreSQL不同索引类型(btree & hash)的性能问题

    在关系型数据库调优中,查询语句涉及到的索引类型是不得不考虑的一个问题.不同的类型的索引可能会适用不同类型的业务场景.这里我们所说的索引类型指的是访问方法(Access Method),至于从其他维度区 ...

  10. 虚拟机系列 | JVM运行时数据区

    本文源码:GitHub·点这里 || GitEE·点这里 一.内存与线程 1.内存结构 内存是计算机的重要部件之一,它是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都在内存中进行,内存性能的强弱 ...