Loading

通过注解反射优化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中,通过反射读取,将Methodtypemethod按照键值对的形式存入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即可,提高了代码可读性和易维护性

posted @ 2022-04-15 14:47  xbsNotes  阅读(114)  评论(0编辑  收藏  举报