前提

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

对外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. 返回boolean的mybatis查询

    注意:返回数量为0时函数返回值为false,返回数量为非零值时为true. Java函数: boolean hasSameServiceCode(@Param("oldDepotCd&quo ...

  2. 局域网内笔记本分屏到android手机上

    前提 笔记本电脑1台 安卓/ios手机1部 局域网 spacedesk 预览 参考: https://www.appinn.com/spacedesk https://spacedesk.net/de ...

  3. 解Bug之路-串包Bug

    解Bug之路-串包Bug 笔者很热衷于解决Bug,同时比较擅长(网络/协议)部分,所以经常被唤去解决一些网络IO方面的Bug.现在就挑一个案例出来,写出分析思路,以飨读者,希望读者在以后的工作中能够少 ...

  4. python之requests.session()使用

    背景:使用requests.session会话对象先登录至豆瓣网,再进入“我的豆瓣”. 首先说一下,为什么要进行会话保持的操作? requests库的session会话对象可以跨请求保持某些参数. 说 ...

  5. 漏洞扫描工具acunetix12会遇到的问题

    1.如果安装好之后,打开工具时显示无法访问,首先去看任务管理器当中,acunetix的服务是否启动了 2.如果忘记了账号密码,可以在安装目录下,双击ChangePassword.exe进行重置密码

  6. 【深入理解Linux内核架构】6.6 资源分配

    一段摘自<Linux设备驱动程序>的话: 每种外设都通过读写寄存器进行控制.大部分外设都有多个寄存器,不管是内存地址空间还是I/O地址空间,这些寄存器的访问地址都是连续的. 在硬件层,内存 ...

  7. 【高并发】面试官:Java中提供了synchronized,为什么还要提供Lock呢?

    写在前面 在Java中提供了synchronized关键字来保证只有一个线程能够访问同步代码块.既然已经提供了synchronized关键字,那为何在Java的SDK包中,还会提供Lock接口呢?这是 ...

  8. ES6 数组方法库

    文章目录 多维数组降维成一维数组 reduce() 回调 flat() 多维数组降维成一维数组 reduce() var arr1 = [[0, 1], [2, 3], [4, 5]]; var ar ...

  9. 关于CountDownLatch、CyclicBarrier和Semaphore

    这次工作使用CountDownLatch来将异步的通信改成同步 扩散了解下其他两种 Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中 ...

  10. 2020华为杯数学建模B题-RON建模 赛后总结与分析

    好久好久没有写博客了...挺累的,从二月份开始找暑期实习,接着在进行暑期实习,然后马不停蹄地进行秋招,现在总算结束实习,前两天又参加了华为杯数学建模竞赛,感觉接下来就会很轻松了,希望能好好休息休息.这 ...