简介
在项目实践过程,尤其是测试时,经常需要生成大量的对象实例的情况。如果手动一个个的new对象,太麻烦了,下面我们写一个工具,以期最终能够使用这个工具能够简便的生成各种类(JavaBean、实体类)的对象。
实现 1、引入随机数工具类参考博客:随机工具类
2、自定义注解用来生成的对象的类上的注解,用来限制对象属性的值的类型or范围……
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ObjectFactory {
/**
* 是否忽略此字段
*
* @return 默认不忽略
*/
boolean ignore() default false;
/**
* 数字整数部分最大值
* 只作用于数字类型的字段
*
* @return 返回最大值
*/
int max() default 100;
/**
* 数字整数部分最小值
* 只作用于数字类型的字段
*
* @return 返回最小值
*/
int min() default 0;
/**
* 精度
* 作用于Float、Double、BigDecimal 小数部分长度
*
* @return 返回精度
*/
int precision() default 2;
/**
* 字符串类型
* @return
*/
StringType type() default StringType.LETTER_LOWERCASE;
/**
* 最大长度
* 只作用于String类型的字段
*
* @return 返回最大长度
*/
int maxLen() default 16;
/**
* 最小长度
* 只作用于String类型的字段
*
* @return 返回最小长度
*/
int minLen() default 8;
}
3、自定义枚举
用来限制待生成对象的类的String类型的字段所需要赋值的数据的类型。
public enum StringType {
// 1纯数字,2纯小写,3纯大写,4大小写,5数字字母混合,6汉字字符串
DIGIT(1,"DIGIT"),
LETTER_LOWERCASE(2,"LETTER_LOWERCASE"),
LETTER_UPPERCASE(3,"LETTER_UPPERCASE"),
LETTER_LOWER_UPPER_CASE(4,"LETTER_LOWER_UPPER_CASE"),
LETTER_DIGIT(5,"LETTER_DIGIT"),
CHINESE_NAME(6,"CHINESE_NAME"),
;
private int code;
private String msg;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
StringType(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
4、具体生成对象的工具类
public class ObjUtil {
private ObjUtil() {
}
public static Object build(Class clazz) throws Exception {
Object obj = clazz.getDeclaredConstructor().newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
ObjectFactory annotation = field.getDeclaredAnnotation(ObjectFactory.class);
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
Method method = pd.getWriteMethod();
//获取方法形参的类型
Class[] parameterTypes = method.getParameterTypes();
for (Class parameterType : parameterTypes) {
if (parameterType == Integer.class) {
method.invoke(obj, RandomUtil.genInteger(1000, 9999)); // obj.setDeptno(234);
}
if (parameterType == String.class) {
if (annotation != null) {
int minLen = annotation.minLen();
int maxLen = annotation.maxLen();
String str = RandomUtil.genString(annotation.type().getCode(), (int) (Math.random() * (maxLen - minLen + 1) + minLen));
method.invoke(obj, str);
}
}
if (parameterType == LocalDate.class) {
method.invoke(obj, RandomUtil.genLocalDate("1999-9-21", "2022-2-22"));
}
if (parameterType == BigDecimal.class) {
method.invoke(obj, new BigDecimal(Math.random() * 90000 + 10000));
}
}
}
return obj;
}
}
注:如果待生成的类中有其它类型的属性,可以在build()方法中填对相应类型的处理,从而拓展程序的功能。
测试 待生成对象的工具类public class Dept {
private Integer deptno;
@ObjectFactory(type = StringType.LETTER_UPPERCASE,minLen = 10,maxLen = 35)
private String dname;
private String loc;
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept{" +
"deptno=" + deptno +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
}
测试代码
public static void main(String[] args) throws Exception {
Object obj = ObjUtil.build(Dept.class);
System.out.println(obj);
}
结果