反射 - 多个子类的方法缓存

时间:2017-12-14 15:02:01

标签: java caching reflection

我有一个abstract类,它由多个具体类扩展。 抽象类初始化块获取当前类层次结构中搜索特定注释方法的所有方法。

ConcreteClass2 > ConcreteClass1 > AbstractClass
OtherConcrete1 > AbstractClass
{
   ...

   final List<Method> methods = new ArrayList<>(16);
   Clazz<?> clazz = getClass();

   while (clazz != Object.class) {
      for (final Method method : clazz.getDeclaredMethods()) {
         if (method.isAnnotationPresent(MyAnnotation.class)) {
            methods.add(method);
         }
      }

      clazz = clazz.getSuperclass();
   }

   METHODS.put(getClass(), methods);

   ...
}

这些具体类在Web /应用程序服务器中实例化,并在Servlet内使用。

本身Reflection不是最快的,因为我不想在每次实例化具体类型时重复扫描(new),缓存注释的最佳策略是什么? Method

我实际上使用ConcurrentHashMap作为<Class<? extends AbstractClass>, List<Method>>,并且在初始化块中,我检查Map是否已经包含最上面的具体类型的条目。

但我不认为这是处理它的最佳方法。顺便说一句,我不能有外部依赖。

1 个答案:

答案 0 :(得分:1)

如果您使用的是Java 8,请使用computeIfAbsent以避免使用注释重新计算方法集:

private static final ConcurrentMap<Class<?>,List<Method>> METHODS = new ConcurrentHashMap<>();
...
Clazz<?> clazz = getClass();
METHODS.computeIfAbsent(clazz, c -> findMethods(c));
...
private static List<Method> findMethods(Class<?> clazz) {
    final List<Method> methods = new ArrayList<>(16);
    while (clazz != Object.class) {
        for (final Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(MyAnnotation.class)) {
                methods.add(method);
            }
        }
        clazz = clazz.getSuperclass();
    }
    return methods;
}

这会缓存每个类的方法,并避免为同一个类重新计算List<Method>