반응형
- 구체적인 클래스 타입을 알지 못하더라도 해당 클래스의 메서드, 변수 등에 접근할 수 있는 기능이다.
- 작성 시점에는 알 수 없지만 실행 중에는 가져와 실행해야 하는 경우 필요하다. 이벤트 버스처럼.
val cls = obj::class.java
val m = cls.getDeclaredMethod("doSomething", String::class.java)
m.isAccessible = true
m.invoke(obj, "hello")
- getDeclaredMethod로 이름이 "doSomething"인 메서드를 찾아 실행 중에 호출하는 예시 코드다.
- 이벤트 버스 라이브러리에서도 @Subscribe 어노테이션 메서드를 리플렉션으로 찾는 로직을 확인할 수 있다.
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
- 근데, 난독화 시에는 이름 변경으로 인해 오류가 발생할 수 있기에 이 부분에 대한 @Keep 처리는 필요하다.
반응형