[Spring] DI Annotation

배창민·2025년 10월 14일
post-thumbnail

스프링 DI 애노테이션


1) DI 기본 개념

  • 의존성 주입(DI) 은 객체 생성·연결 제어를 컨테이너가 담당해 결합도를 낮춘다. 스프링에선 ApplicationContext 가 빈을 찾아 주입한다.

2) @Autowired — 타입 기반 주입

  • 주입 방식

    • 필드 주입: 간단하지만 테스트/불변성에 약함.

      @Service
      public class BookService {
        @Autowired private BookDAO bookDAO;
      }
    • 생성자 주입(권장): 의존성 보장, 불변성 확보, 테스트 용이. 생성자가 하나면 생략해도 동작.

      @Service
      public class BookService {
        private final BookDAO bookDAO;
        @Autowired
        public BookService(BookDAO bookDAO){ this.bookDAO = bookDAO; }
      }
    • 세터 주입: 선택적 의존성이나 프레임워크 바인딩에 유용.

      @Service
      public class BookService {
        private BookDAO bookDAO;
        @Autowired public void setBookDAO(BookDAO dao){ this.bookDAO = dao; }
      }
  • 컨테이너 부팅/스캔

    ApplicationContext ctx =
        new AnnotationConfigApplicationContext("com.ohgiraffers.section01");

3) 동일 타입 빈이 여러 개일 때

3-1) @Primary — 우선 빈 지정

@Component @Primary
public class Charmander implements Pokemon { ... }
  • 같은 타입 충돌 시 우선 주입 대상이 된다(한 클래스만 지정).

3-2) @Qualifier — 이름으로 특정

@Service
public class PokemonService {
  @Autowired @Qualifier("pikachu")
  private Pokemon pokemon;
}
  • 생성자 파라미터에도 지정 가능.
  • 우선순위: @Qualifier@Primary 보다 우선한다.

4) 컬렉션 주입

  • 같은 타입 빈을 한꺼번에 주입 가능.
@Service
public class PokemonService {

  private final List<Pokemon> list;
  private final Map<String, Pokemon> map;

  @Autowired
  public PokemonService(List<Pokemon> list) { this.list = list; }

  @Autowired
  public PokemonService(Map<String, Pokemon> map) { this.map = map; }
}
  • 정렬 기준: 빈 이름의 사전순으로 List/Map 에 담긴다.

5) 자바 표준 애노테이션

5-1) @Resource (javax.annotation)

@Service
public class PokemonService {
  @Resource(name = "pikachu")
  private Pokemon pokemon; // 이름으로 주입, 없으면 타입으로
}
  • 필드/세터 주입 지원, 생성자 주입 불가.

5-2) @Inject (javax.inject) + @Named

@Service
public class PokemonService {
  private final Pokemon pokemon;
  @Inject
  public PokemonService(@Named("pikachu") Pokemon pokemon) {
    this.pokemon = pokemon;
  }
}
  • 타입 기반 주입. 필드/세터/생성자 모두 가능. 특정 빈은 @Named("name") 로 지정.

6) 선택 가이드

  • 생성자 주입 우선: 의존성 미주입 시 애플리케이션 시작 단계에서 즉시 오류 감지, 불변성 확보, 테스트 용이.
  • @Qualifier: 동일 타입 다수 빈 환경의 기본 선택지.
  • @Primary: 글로벌 기본값처럼 쓰고, 필요 시 @Qualifier 로 덮어쓴다.
  • 컬렉션 주입: 전략 집합, 플러그인 구조에 유용.
  • 자바 표준이 필요한 환경: @Resource, @Inject 도입.

7) 치트시트

구분제공지원 방식빈 탐색 우선순위특정 빈 지정
@AutowiredSpring필드, 생성자, 세터타입 → 이름@Qualifier("name")
@ResourceJava필드, 세터이름 → 타입@Resource(name="name")
@InjectJava필드, 생성자, 세터타입 → 이름@Named("name")

8) 코드 스니펫 모음

  • 컨텍스트 부팅

    new AnnotationConfigApplicationContext("com.ohgiraffers.section02");
  • 동일 타입 충돌 해결

    @Primary class A implements T {}
    @Component @Qualifier("b") class B implements T {}
  • 리스트/맵 주입 후 실행

    list.forEach(T::run);
    map.forEach((k,v)->v.run());

한 줄 요약

  • 생성자 주입을 기본으로, 다중 빈은 @Qualifier 로 정확히 지정하고 전역 기본은 @Primary 로 둔다. 필요 시 컬렉션 주입과 표준 애노테이션(@Resource, @Inject)을 조합해 상황에 맞게 선택한다.
profile
개발자 희망자

0개의 댓글