近期在做老项目的重构,需要对原有的业务方法进行优化和重构,但需要保持原有逻辑不变,故想写个对比框架,能实时对新老方法进行对比测试。以下代码只是一个简单的实现,可扩展实现的还有很多,例如:
1、实现远程调用,对两个不同服务的方法进行对比测试
2、通过注解标明需要进行对比的字段
3、对比结果如何展示更优雅
4、如何异步进行对比
自定义一个注解,用于标注需要对比的方法。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodCompare {
Class clazz();
String methodName();
}
对标注了注解的方法进行切面处理。
@Aspect
@Component
public class MethodCompareAspect {
@Autowired
SpringInvoke springInvoke;
@Around("@annotation(xx.xx.xx.MethodCompare)")
public Object aroundCompareMethod(ProceedingJoinPoint joinPoint) throws Throwable {
//从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取方法的入参,可以获取方法入参的注解
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
}
//获取方法上的注解
MethodCompare methodCompare = method.getAnnotation(MethodCompare.class);
String methodName = methodCompare.methodName();
Class clazz = methodCompare.clazz();
//参数序列化
Object[] args = joinPoint.getArgs();
Object[] newArgs = new Object[args.length];
for (int i = 0; i < args.length; i++) {
String argsStr = JSON.toJSONString(args[i]);
newArgs[i] = JSON.parseObject(argsStr, args[i].getClass());
}
//这里可以改为异步
Object o = springInvoke.springInvoke(clazz, methodName, newArgs);
System.out.printf("对比方法返回值" + JSON.toJSONString(o));
//调用原有逻辑
Object obj = joinPoint.proceed();
System.out.printf("原有方法返回值" + JSON.toJSONString(obj));
return obj;
}
}
从spring容器中获取对象并调用。
@Service
public class SpringInvoke implements ApplicationContextAware {
private ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
public Object springInvoke(Class clazz, String methodName, Object[] args) throws Exception {
// 获取Spring容器中的bean
Object bean = context.getBean(clazz);
// 获取方法对象
Method method = null;
if (null != args && args.length > 0) {
Class[] argsClass = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argsClass[i] = args[i].getClass();
}
method = clazz.getMethod(methodName, argsClass);
} else {
method = clazz.getMethod(methodName);
}
return method.invoke(bean, args);
}
}