概述
Java 注解、反射、泛型使用实践
通过 注解、反射、泛型 实现一个通用的实体类字段计算工具
近期工作中,在做的项目,需要进行各种报表的计算。
对象字段间进行加减乘除等计算,以及汇总计算
场景:
假设有这样一个实体类:
@Data
public class ClockingInEntity {
/**
* 迟到次数
*/
private Integer lateCount;
/**
* 缺卡次数
*/
private Integer notClockInCount;
/**
* 缺卡扣款
*/
private BigDecimal notClockInWithhold;
/**
* 迟到扣款
*/
private BigDecimal lateWithhold;
}
用户填写 迟到次数和缺卡次数,需要自动计算缺卡扣款和迟到扣款:
缺卡扣款 = 缺卡次数 * 100
迟到扣款 = 迟到次数 * 200
如果字段很少的话,使用代码的方式来计算没啥问题,但是这个系统有很多地方都要进行各字段之间的计算,如果使用硬编码进行计算,那么公式改变了,就得改代码逻辑。
我想能否将公式配置到某个地方,再写一个触发计算的方法,来计算呢?如果计算公式改变,那么改变配置的公式即可。
于是,我想到了使用注解来配置公式。
接着,开始了 Java 注解和反射 的详细学习,之前只是随便看了下,没用过。
通过注解将公式配置到注解参数上,于是实体类变成了:
ClockingInEntity.Java
@Data
public class ClockingInEntity {
/**
* 迟到次数
*/
@USummaryAnnotation(needSum = true)
private Integer lateCount;
/**
* 缺卡次数
*/
@USummaryAnnotation(needSum = true)
private Integer notClockInCount;
/**
* 缺卡扣款
*/
@USummaryAnnotation(needSum = true)
@UFormulaAnnotation(formula = "[notClockInCount]*100",accuracy = 2,sort = 1)
private BigDecimal notClockInWithhold;
/**
* 迟到扣款
*/
@USummaryAnnotation(needSum = true)
@UFormulaAnnotation(formula = "[lateCount]*200",accuracy = 2,sort = 2)
private BigDecimal lateWithhold;
public ClockingInEntity(Integer lateCount, Integer notClockInCount) {
this.lateCount = lateCount;
this.notClockInCount = notClockInCount;
}
public ClockingInEntity() {
}
}
然后通过反射获取注解上的公式等配置信息进行计算,并将结果赋值到对应字段即可
为了让计算工具具有通用行,使用了泛型
public interface CalcService {
/**
* 对一个实体类进行计算 配合 UFormulaAnnotation 注解使用
* @param entityClass 目标实体 clazz
* @param <T>
* @return
*/
<T> T doOneEntityCalc(Class<T> entityClass, T entity);
/**
* 对实体列表进行计算 UFormulaAnnotation 注解使用
* @param entityClass 目标实体 clazz
* @param entities 实体列表
* @param <T>
* @return
*/
<T> List<T> doEntitiesCalc(Class<T> entityClass, List<T> entities);
/**
* 汇总计算 USummaryAnnotation 注解使用
* @param entityClass 目标实体 clazz
* @param entities 实体列表
* @param <T>
* @return
*/
<T> T doSummaryCalc(Class<T> entityClass, List<T> entities,T summaryEntity);
/**
*两个实体相除 UDivisionAnnotation 注解使用
* @param entityClass 目标实体 clazz
* @param divisorEntity 除数
* @param dividendEntity 被除数
* @param resultEntity 结果实体
* @param <T>
* @return
*/
<T> T doEntityDivisionCalc(Class<T> entityClass, T divisorEntity, T dividendEntity, T resultEntity);
CalcServiceImpl.java 代码太长这里就不贴了,可到 https://gitee.com/zranfly/easy-calc.git 获取
最终通过简单的调用即可进行实体间字段计算,效果如下:
public class MainTest {
public static void main(String[] args) {
CalcService calcService = new CalcServiceImpl();
ClockingInEntity entity1 = new ClockingInEntity(2,10);
ClockingInEntity entity2 = new ClockingInEntity(3,11);
ClockingInEntity entity3 = new ClockingInEntity(4,23);
List<ClockingInEntity> entities = Lists.newArrayList(entity1,entity2,entity3);
// 单个实体计算
System.out.println("===========计算前================");
System.out.println(JSON.toJSONString(entity1));
System.out.println("===========计算后================");
calcService.doOneEntityCalc(ClockingInEntity.class,entity1);
System.out.println(JSON.toJSONString(entity1));
// 多个实体计算
System.out.println("===========批量计算================");
calcService.doEntitiesCalc(ClockingInEntity.class,entities);
System.out.println(JSON.toJSONString(entities));
// 汇总计算
System.out.println("===========汇总计算================");
ClockingInEntity totalEntity = calcService.doSummaryCalc(ClockingInEntity.class, entities, new ClockingInEntity());
System.out.println(JSON.toJSONString(totalEntity));
}
输出结果
===========计算前================
{"lateCount":2,"notClockInCount":10}
===========计算后================
{"lateCount":2,"lateWithhold":400.00,"notClockInCount":10,"notClockInWithhold":1000.00}
===========批量计算================
[{"lateCount":2,"lateWithhold":400.00,"notClockInCount":10,"notClockInWithhold":1000.00},{"lateCount":3,"lateWithhold":600.00,"notClockInCount":11,"notClockInWithhold":1100.00},{"lateCount":4,"lateWithhold":800.00,"notClockInCount":23,"notClockInWithhold":2300.00}]
===========汇总计算================
{"lateCount":9,"lateWithhold":1800.00,"notClockInCount":44,"notClockInWithhold":4400.00}
代码获取:https://gitee.com/zranfly/easy-calc.git
代码还有优化空间,后续有时间再做优化
最后
以上就是老迟到煎蛋为你收集整理的Java 注解、反射、泛型使用实践 | 实现一个通用的实体类字段计算工具的全部内容,希望文章能够帮你解决Java 注解、反射、泛型使用实践 | 实现一个通用的实体类字段计算工具所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复