通过注解反射优化switch-case的方法调用
需要调用的方法:
public interface IMethodService {
@OperationType(methodType = Methodtype.CHECK)
String check();
@OperationType(methodType = Methodtype.ADD)
String add();
@OperationType(methodType = Methodtype.DELETE)
String delete();
@OperationType(methodType = Methodtype.UPDATE)
String update();
@OperationType(methodType = Methodtype.SELECT)
String select();
正常调用:
如果方法过多(上百),代码易读性,维护行较差
@org.junit.Test
public void testDo() {
IMethodService methodService = new MethodServiceImpl();
Methodtype methodType = Methodtype.UPDATE;
Object result;
switch (methodType) {
case ADD:
result = methodService.add();
break;
case DELETE:
result = methodService.delete();
break;
case UPDATE:
result = methodService.update();
break;
case CHECK:
result = methodService.check();
break;
case SELECT:
result = methodService.select();
break;
default:
result = null;
}
System.out.println(result);
}
通过加注解,使用反射调用方法:
核心思想就是将Methodtype
放入注解value中,通过反射读取,将Methodtype
—method
按照键值对的形式存入map
中
//定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OperationType {
/**
* 需要执行的方法
*/
Methodtype methodType();
}
//增加注解调用方法工具类
public class AnnotationUtils {
private AnnotationUtils() {
}
/**
* 通过反射调用执行方法
*/
public static Object doByAnnotation(Object obj, Class<? extends Annotation> annotation, Methodtype methodKey, Object... inputs) throws InvocationTargetException, IllegalAccessException {
Map<String, AccessibleObject> methodMap = getAnnotatedMethodMap(obj.getClass(), annotation, methodKey.name());
Method method = (Method) methodMap.get(methodKey.name());
if (Objects.isNull(method)) {
System.out.println("未找到对应的方法, operation:{ " + methodKey + "}");
return null;
}
return method.invoke(obj, inputs);
}
/**
* 获取被注解标注的方法map
* @param clazz 目标类
* @param annotation 操作类型注解
* @return 获取被注解标注的方法map
*/
private static Map<String, AccessibleObject> getAnnotatedMethodMap(Class<?> clazz, Class<? extends Annotation> annotation, String methodKey) {
Map<String, AccessibleObject> methodMap = new HashMap<>();
//获取interface
List<Class<?>> interfaces = Arrays.stream(clazz.getInterfaces()).collect(Collectors.toList());
Assert.notNull(interfaces, "interfaces不能为空");
interfaces.forEach(i -> {
Arrays.stream(i.getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(annotation))
.forEach(method -> {
methodMap.put(method.getAnnotation(OperationType.class).methodType().name(),
method);//按照注解的value存入methodMap
});
});
return methodMap;
}
}
//通过注解反射的方式调用
@org.junit.Test
public void testDoByAnnotation() {
IMethodService methodService = new MethodServiceImpl();
Methodtype methodType = Methodtype.UPDATE;
try {
Object result = AnnotationUtils.doByAnnotation(methodService, OperationType.class, methodType);
System.out.println(result);
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
通过反射调用后续扩展只需要在接口IMethodService
中增加对应的方法和注解参数@OperationType
即可,提高了代码可读性和易维护性