[Spring Boot] 2. Reflection_2.Ex02

김미숙's avatar
Mar 20, 2025
[Spring Boot] 2. Reflection_2.Ex02

Reflection & Annotation

Annotation

‼️

Annotation (Ex. 깃발 🚩)

  • 코드에 메타데이터를 추가하는 기능
  • 코드 가독성을 높이고, 유지보수를 쉽게 해주는 강력한 도구
  • 주석처럼 보이지만, 실제로 코드 실행이나 컴파일에 영향을 미칠 수 있다
  • 소스 코드가 컴파일되거나 실행될 때 컴파일러 및 다른 프로그램에게 필요한 정보를 전달해 주는 문법 요소
Annotation
설명
@Retention
Annotation 유지 범위 지정 (컴파일러, 런타임 등)
@Target
Annotation 적용 대상 지정 (메서드, 클래스 등)
@Documented
문서화 도구(Javadoc)에서 어노테이션 포함 여부
@Inherited
상속될 수 있는 Annotation 지정
@Repeatable
같은 Annotation을 여러 번 사용할 수 있도록 허용

@RequestMapping

package ex02; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RequestMapping { String value(); }
  • @Retention(RetentionPolicy.RUNTIME)
    • 해당 Annotation이 Runtime에도 사라지지 않고 유지되게 해주며, Reflection이 이를 활용할 수 있게 된다
  • @Target(ElementType.METHOD)
    • 전용 Type을 결정
    • 여기서 Method Type을 설정하면, Method 전용 Annotation이 된다
    • 이렇게 Method로 설정이 되어있다면 해당 Annotation은 Method드 위에 붙여야 한다
  • String URI();
    • RequestMapping Annotation의 속성값
    • 따라서 Annotation이 사용될때 속성값 역시 받아올 수 있다
 

Reflection

Dispatcher

package ex02; import java.lang.reflect.Method; public class Dispatcher { UserController con; public Dispatcher(UserController con) { this.con = con; } public void routing(String path) { // /login Method[] methods = con.getClass().getMethods(); for (Method method : methods) { RequestMapping rm = method.getAnnotation(RequestMapping.class); if (rm == null) continue; // 다음 for문으로 바로 넘어감 if (rm.value().equals(path)) { try { method.invoke(con); } catch (Exception e) { throw new RuntimeException(e); } } } } }

👉 Reflection 구현하는 핵심 코드

Method[] methods = con.getClass().getMethods();
Method[]: java.lang.reflect에 선언된 메서드를 저장할 수 있는 객체 배열
.getClass(): 클래스의 메타 데이터를 조회
.getMethods(): 조회된 클래스에 선언된 모든 public 메서드를 가져온다
 

👉 Reflection 구현 완성

for (Method method : methods) { RequestMapping rm = method.getAnnotation(RequestMapping.class); if (rm == null) continue; // 다음 for문으로 바로 넘어감 if (rm.value().equals(path)) { try { method.invoke(con); } catch (Exception e) { throw new RuntimeException(e); } }
RequestMapping rm = method.getAnnotation(RequestMapping.class): RequestMapping Annotation이 있는 클래스에서 가져온 메서드를 rm에 담는다
for each 구문에서 배열에 담긴 메서드를 순회
rm.value()이 검색중인 (path) 요청값이랑 비교
➡ 비교값이 메서드 이름과 일치하면 method.invoke(con)으로 해당 메서드 실행
 

UserController

⚠ 직접 만든 Annotation을 사용하기 위해서는 같은 Package 안에 존재해야 한다
package ex02; public class UserController { @RequestMapping("/login") public void login() { System.out.println("login call"); } @RequestMapping("/join") public void join() { System.out.println("join call"); } @RequestMapping("/logout") public void logout() { System.out.println("logout call"); } @RequestMapping("/userinfo") public void userinfo() { System.out.println("userinfo call"); } }
 

App

  • Dispatcher를 Heap에 띄우고, 그 안에 UserController를 담는다
package ex02; public class App { public static void main(String[] args) { Dispatcher ds = new Dispatcher(new UserController()); ds.routing("/login"); ds.routing("/join"); ds.routing("/logout"); ds.routing("/userinfo"); } }
출력 결과
C:\workspace\tools\jdk-21\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\lib\idea_rt.jar=53858:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\workspace\spring_lec\ref\out\production\ref ex02.App login call join call logout call userinfo call Process finished with exit code 0
Share article

parangdajavous