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

时间:2023-03-09 19:43:31
如何从0到1的构建一款Java数据生成器-第二章

前提

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

对外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个坑。精彩继续。