abstract
클래스가 여러 개의 구체적인 클래스로 확장되었습니다. 추상 클래스 초기화 블록은 특정 주석이 달린 메소드를 검색하는 현재 클래스 계층의 모든 메소드를 가져옵니다. 리플렉션 - 여러 서브 클래스에 대한 메서드 캐싱
{
...
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);
...
}
이 구체적인 클래스
ConcreteClass2 > ConcreteClass1 > AbstractClass
OtherConcrete1 > AbstractClass
는 웹/응용 프로그램 서버에서 인스턴스화하고
Servlet
의 내부에 사용된다. 자체
Reflection
으로
가장 빠른 아니다, 나는 검사에게 구체적인 형식이 인스턴스화 될 때마다 (new
)를 반복하지 않는 한, 주석 Method
년대를 캐시 할 수있는 최선의 전략은 무엇인가.
실제로 을 <Class<? extends AbstractClass>, List<Method>>
으로 사용하고 있습니다. 초기화 블록에서 Map
에 이미 최상위 콘크리트 유형 항목이 있는지 확인합니다.
그러나 나는 이것을 처리하는 가장 좋은 방법이라고 생각하지 않습니다. 그런데 외부 의존성을 가질 수는 없습니다. 이 클래스 당 방법을 캐시, 같은 클래스 List<Method>
을 재 계산 피할 것이다
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;
}
:
웹 응용 프로그램이 시작된 후에 주석에 대한 일회성 스캔 (스프링과 비슷 함) 일 수 있습니다. –
@AndrewS 응용 프로그램 시작을 수정할 수 없습니다. – LppEdd