Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

아이템 39. 명명 패턴보다 애너테이션을 사용하라 #39

Closed
ksy90101 opened this issue Dec 31, 2020 · 4 comments
Closed

아이템 39. 명명 패턴보다 애너테이션을 사용하라 #39

ksy90101 opened this issue Dec 31, 2020 · 4 comments

Comments

@ksy90101
Copy link
Contributor

No description provided.

@jiaekim123
Copy link
Contributor

아이템 39-3 마커애너테이션을 처리하는 프로그램에서 리플렉션 처리 과정 중 궁금한 점이 있습니다.
예시는 아래와 같았는데

public class RunTests {
    public static void main(String[] args) throws Exception {
        int tests = 0;
        int passed = 0;
        Class<?> testClass = Class.forName(args[0]); // item39.Sample
        for (Method m : testClass.getDeclaredMethods()) { // 리플렉션으로 사용할 메서드 m1, m2...
            if (m.isAnnotationPresent(Test.class)) { // @Test 어노테이션이 있으면
                tests++;
                try {
                    m.invoke(null); // 실제 메서드 실행
                    passed++; // 성공하면 passed++
                } catch (InvocationTargetException wrappedExc) { // 테스트에서 예외를 던지면 리플렉션 매커니즘이 InvocationTargetException으로 감싸서 다시 던진다.
                    Throwable exc = wrappedExc.getCause();
                    System.out.println(m + " 실패: " + exc);
                } catch (Exception exc) {
                    // 테스트에서 잡지 못한 예외가 있다는것은 @Test 애너테이션을 잘못 사용했다는 뜻.
                    System.out.println("잘못 사용한 @Test: " + m);
                }
            }
        }
        System.out.printf("성공: %d, 실패: %d%n",
                passed, tests - passed);
    }
}

@test 어노테이션을 달아둔 메서드가 실패하면 InvocationTargetException 으로 들어오고, @test 어노테이션을 잘못 사용할 경우에는 Exception 이 발생한다고 되어 있었습니다, 리플렉션에서는 메서드 내부에서 Exception이 발생하면 무조건 InvocationTargetException 으로 던지게 된다고 써있는데, 실제로 익셉션이 NullPointException, IlligalException, ClassCastExcpetion 등이 발생할 요소가 있고 이런 것을 분리해서 롤백/확인을 하고 싶다면 어떻게 해야 하나요?

@pkch93
Copy link
Contributor

pkch93 commented Feb 17, 2021

리플렉션에서는 무조건 InvocationTargetException으로 던지는건 신기하네요 ㅋㅋㅋ
Throwable exc = wrappedExc.getCause();에서 실제 메서드에서 발생한 root cause를 가져올 수 있는걸로 보이네요. 이를 활용하면 되지 않을까 싶어요.

벨덩(?)에서도 Throwable.getCause()를 활용하라고 하네요

@jiaekim123
Copy link
Contributor

@pkch93 아하! 그럼 getCause()로 나온 Exception 이름들을 클래스 이름으로 분기태워서 해야겠네요.
InvocationTargetException에서 getCause()메서드와 함께 getTargetException()도 있길래 실험해보는데 동일하게 Exception 이름이 반환되네요. cause랑 동일한 역할을 하는 친구인 것 같습니다.

https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/InvocationTargetException.html#getTargetException()

@pkch93
Copy link
Contributor

pkch93 commented Feb 17, 2021

네넵 getCause()getTargetException()이랑 동일한 역할을 하네요 ㅋㅋ

    public Throwable getTargetException() {
        return target;
    }

    public Throwable getCause() {
        return target;
    }

스프링도 리플렉션을 사용하고 있어서 어떻게 처리하나 봤는데 getTargetException()으로 실제 발생한 Exception을 가져와서 분기처리하네요.

org.springframework.web.method.support.InvocableHandlerMethod 입니다.

	@Nullable
	protected Object doInvoke(Object... args) throws Exception {
		ReflectionUtils.makeAccessible(getBridgedMethod());
		try {
			return getBridgedMethod().invoke(getBean(), args);
		}
		catch (IllegalArgumentException ex) {
			assertTargetBean(getBridgedMethod(), getBean(), args);
			String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
			throw new IllegalStateException(formatInvokeError(text, args), ex);
		}
		catch (InvocationTargetException ex) {
			// Unwrap for HandlerExceptionResolvers ...
			Throwable targetException = ex.getTargetException();
			if (targetException instanceof RuntimeException) {
				throw (RuntimeException) targetException;
			}
			else if (targetException instanceof Error) {
				throw (Error) targetException;
			}
			else if (targetException instanceof Exception) {
				throw (Exception) targetException;
			}
			else {
				throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
			}
		}
	}

ksy90101 added a commit that referenced this issue Feb 28, 2021
[#39][B팀] 명명 패턴보다 애너테이션을 사용하라
ksy90101 added a commit that referenced this issue Oct 30, 2021
[#39][2기] 명명 패턴보다 애너테이션을 사용하라
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants