前提

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

对外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. 再试Count(*) 与Count(*) 列

    试问,如果有一张表有两个字段,均可为空,插入两条首个字段为空的记录,再插入两条第二字段为空的记录,问count(*)和count(列)结果如何? 答案:count(*)是正常的四条,而count(列) ...

  2. Mysql用户权限控制(5.7以上版本)

    1.1. 最简单的MySql权限   最简单也是最高效的,如果解决新手们删库跑路的问题其实也是很简单的,对于正式库只给一个增删改查的权限,或者只给一个查询权限(是不是就解决了删库的可能性?) 使用Ro ...

  3. Ubuntu修改默认Python版本,你了解多少~

    目录 1 查看Python版本 1.1 查看装有哪些版本 1.2 查看默认版本 2 修改Python默认版本 2.1 基于文件修改 2.2 基于软链接修改 1 查看Python版本 1.1 查看装有哪 ...

  4. UI中列表

    1.ul.ol.dl

  5. 漏桶、令牌桶限流的Go语言实现

    限流 限流又称为流量控制(流控),通常是指限制到达系统的并发请求数. 我们生活中也会经常遇到限流的场景,比如:某景区限制每日进入景区的游客数量为8万人:沙河地铁站早高峰通过站外排队逐一放行的方式限制同 ...

  6. [LeetCode]196. 删除重复的电子邮箱(delete)

    题目 编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个. +----+------------------+ | Id | Email | ...

  7. java安全编码指南之:堆污染Heap pollution

    目录 简介 产生堆污染的例子 更通用的例子 可变参数 简介 什么是堆污染呢?堆污染是指当参数化类型变量引用的对象不是该参数化类型的对象时而发生的. 我们知道在JDK5中,引入了泛型的概念,我们可以在创 ...

  8. (专题一)07 matlab中字符串的表示

    matlab中,字符串使用单引号括起来的字符序列 >>xm='Central South University' >>xm(1:3) ans= Cen 截取1--3这三个字符, ...

  9. hystrix文档翻译之如何使用

    Hello World! 使用HystrixCommand实现“Hello World”. public class CommandHelloWorld extends HystrixCommand& ...

  10. 在Winform程序中使用Spire.Pdf实现页面添加印章处理

    在一些场合,我们往往需要使用印章来给每页文档加盖一个印章,以表示该文档经过某个部门的认证的,常规的做法就是打印文档后盖章,如果需要电子档再行扫描一下.这样的的处理,如果文档很多,且仅仅需要电子文档的就 ...