[JAVA] 70. 파라미터 어노테이션으로 객체 주입하는 방법

윤설안's avatar
Jul 27, 2025
[JAVA] 70. 파라미터 어노테이션으로 객체 주입하는 방법
 
💡
Spring에서 메서드 파라미터에 붙은 어노테이션을 이용하여 객체를 주입 방식을 공부해보았다.

2. 목표 설명

  • @Princiapl SessionUser user 처럼 어노테이션 기반으로 파라미터에 객체를 자동 주입
  • 파라미터별 어노테이션을 리플렉션으로 읽고 처리
  • 타입(Class)을 기반으로 객체를 동적으로 생성하거나 가져오기

3. 핵심 개념

getParameterAnnotations vs getParameterTypes

  • Annotation[][] paramAnnotations: [파라미터 개수][각 파라미터의 어노테이션 수]
    • 파라미터에 여러 어노테이션을 붙일 수 있기 때문에 2차원 배열로 정보를 저장해야 한다.
    • 예시
      • java 복사편집 [ [@A], // 첫 번째 파라미터의 어노테이션들 [@B, @C] // 두 번째 파라미터의 어노테이션들 ]
  • Class<?>[] paramTypes: 각 파라미터가 어떤 타입인지 나타낸다
→ 이 두 가지 정보를 조합하면 어노테이션 + 타입 기반으로 파라미터 주입 로직을 구현할 수 있다

4. instanceof란?

if (annotation instanceof Princiapl)
  • 자바의 연산자
  • 해당 인스턴스가 특정 클래스(또는 인터페이스)의 객체인지 검사할 때 사용
  • annotationAnnotation 타입(부모 타입)이기 때문에 실제로 어떤 어노테이션인지 알 수 없다
  • 그래서 "이 어노테이션이 @Princiapl 어노테이션인지?" 를 검사하는 것
  • boolean 값(true 또는 false)을 반환함
💡 이건 클래스 타입 비교에 쓰는 일종의 "조건 필터"라고 생각하면 된다

5. 파라미터 기반 주입 로직 전체 흐름

for (int i = 0; i < paramAnnotations.length; i++) { for (Annotation annotation : paramAnnotations[i]) { if (annotation instanceof Princiapl) { argsToPass[i] = SessionUser.getInstance(); } } if (argsToPass[i] == null) { if (paramTypes[i] == Model.class) { argsToPass[i] = Model.getInstance(); } } }
  • 각 파라미터마다 붙은 어노테이션을 검사하여 @Princiapl이 있으면 해당 인덱스 위치에 SessionUser 싱글톤 인스턴스를 넣어준다
  • 만약 @Princiapl이 없고 아직 값이 할당되지 않았다면, 파라미터 타입이 Model인 경우 Model 인스턴스를 넣어준다
  • 이렇게 하면 어노테이션과 타입 기반으로 메서드 호출 시 필요한 인자들을 자동으로 채워줄 수 있다

6. 전체 코드

public class App { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String path = sc.nextLine(); Method[] methods = UserController.class.getDeclaredMethods(); UserController uc = new UserController(); for (Method method : methods) { RequestMapping rm = method.getDeclaredAnnotation(RequestMapping.class); if (rm == null) continue; if (rm.value().equals(path)) { Object[] argsToPass = new Object[method.getParameterCount()]; Annotation[][] paramAnnotations = method.getParameterAnnotations(); Class<?>[] paramTypes = method.getParameterTypes(); for (int i = 0; i < paramAnnotations.length; i++) { for (Annotation annotation : paramAnnotations[i]) { if (annotation instanceof Princiapl) { argsToPass[i] = SessionUser.getInstance(); } } if (argsToPass[i] == null) { if (paramTypes[i] == Model.class) { argsToPass[i] = Model.getInstance(); } } } try { method.invoke(uc, argsToPass); } catch (Exception e) { throw new RuntimeException(e); } } } } }
  • 사용자 입력으로 받은 path에 해당하는 메서드를 UserController에서 찾아 실행한다
  • 메서드의 매개변수 개수만큼 배열을 만들고, 각 매개변수에 붙은 어노테이션과 타입 정보를 가져온다
  • 각 파라미터가 @Princiapl이 붙은 경우엔 SessionUser 객체를 넣고, 없으면 타입이 Model인 경우 Model 객체를 넣는다
  • 준비된 인자 배열을 가지고 method.invoke로 메서드를 실행한다
 
Share article

An's Blog