
- Reflection → 속을 비추다 (코드 내부를 보는 것)
- Annotation → JVM이 보는 주석 (힌트)
/스프링에서의 어노테이션 작동법/
1. Reflection 예제
- Reflection 사용하지 않은 코드
1-1 UserController 생성
// 로그인, 회원가입, 유저정보 기능 제공 메소드
package ex01;
public class UserController {
public UserController() {
}
public void login() {
System.out.println("login 호출됨");
}
public void join() {
System.out.println("join 호출됨");
}
public void userinfo() {
System.out.println("userinfo 호출됨");
}
}
1-2 App class 생성
// 사용자가 입력한 URL에 따라 해당 메소드를 호출하도록 작성
package ex01;
// A 개발자
public class app {
public static void main(String[] args) {
String path = "/userinfo";
UserController uc = new UserController();
if (path.equals("/login")) {
uc.login();
} else if (path.equals("/join")) {
uc.join();
} else if (path.equals("/userinfo")) {
uc.userinfo();
}
}
}
1-3 컴파일

→ String path = “/userinfo”; 를 login으로 바꾸면,

위 방식은 단순 path 변수를 통해 /login 또는 /userinfo 경로에 맞춰 UserController의 메소드를 호출. (확장성 떨어짐)
→ 새로운 메소드가 추가될 때 마다 App 클래스도 수정해야하기 때문.
2. Reflection 활용
* 리플렉션은 순서 보장 x
밑의 코드는 UserController 클래스의 메소드를 리플렉션을 통해 탐색하고 그 이름을 출력.
2-1 UserController 생성
package ex02;
public class UserController {
// /board/save-form
@RequestMapping(uri = "/save-form")
public void saveform() { System.out.println("saveform 호출됨"); }
@RequestMapping(uri = "/userinfo")
public void userinfo() {
System.out.println("userinfo 호출됨");
}
@RequestMapping(uri = "/login")
public void login(){
System.out.println("login 호출됨");
}
@RequestMapping(uri = "/join")
public void join(){
System.out.println("join 호출됨");
}
}
2-2 App class 생성
package ex02;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class App {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
String path = "/saveform";
UserController uc = new UserController();
// UserController란 클래스 안에 어떤 메소드들이 있는지 return
Method[] methods = uc.getClass().getMethods();
for (Method mt : methods) {
Annotation anno = mt.getDeclaredAnnotation(RequestMapping.class);
RequestMapping rm = (RequestMapping) anno;
if (rm == null) break;
if (rm.uri().equals(path)) {
mt.invoke(uc);
}
}
}
}
→ Method[ ] methods = uc.getClass().getDeclaredMethods(); 를 통해 UserController 안에 있는 메소드 이름 조회(실행) 가능.
- 실행 코드

mt.invoke(uc); 를 사용하기 위해선 Exception이 필요함
→ 매개변수로 넣은 uc안에 메소드가 존재하지 않을 수 있기 때문
2-3 Annotation 정의
→ 어노테이션 사용 시 메소드 이름 대신 어노테이션 값 기준으로 동적 메소드 호출 가능.
- RequestMapping 어노테이션 정의
package ex02;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) // 해당 깃발은
public @interface RequestMapping {
String uri();
}
2-4 Annotation 적용
package ex02;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class App {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
String path = "/login";
UserController uc = new UserController();
// UserController란 클래스 안에 어떤 메소드들이 있는지 return
Method[] methods = uc.getClass().getMethods();
for (Method mt : methods) {
Annotation anno = mt.getDeclaredAnnotation(RequestMapping.class);
RequestMapping rm = (RequestMapping) anno;
if (rm == null) break;
if (rm.uri().equals(path)) {
mt.invoke(uc);
}
}
}
}
어노테이션을 사용해 각 메소드가 어떤 URL 경로와 매핑되는지 정의 후, 런타임에 이 Mapping 정보를 바탕으로 메소드 호출.
- path 변수만 변경하면 어떤 메소드든 호출 가능
- App 클래스 수정 필요x
Share article