Spring DI(Dependency Injection)
1 minute read
의존 주입에서 ‘의존’
- 한 클래스가 다른 클래스의 메서드를 실행하는 것
- 클래스 내부에서 직접 의존 객체를 생성하는 것이 유지보수 관점에서 문제점을 유발할 수 있다.
DI
- 객체를 직접 생성하는 대신 의존 객체를 전달받는 방식 사용
- e.g. 생성자를 통해 의존 객체를 전달받는다.
- 변경에 대해 유연함을 제공할 수 있다.
Object Assembler
- 객체를 생성하고 의존 객체를 주입해주는 클래스
- 스프링이 DI를 지원하는 Assembler
DI 방식
생성자 방식
- 객체를 생성해 바로 리턴하는 방식
- 빈 객체를 생성하는 시점에 모든 의존 객체가 주입
- 파라미터가 개수가 많아질 경우에, 의존 객체를 일일이 확인하기 위해 수고스러움이 생길 수 있다.
Setter method 방식
- 빈 객체 생성 후, 세터를 활용해 값을 채운 후 리턴하는 방식
- 세터 메서드 이름을 통해 어떤 의존 객체가 주입되는지 명확히 확인할 수 있다
- 제대로 주입해주지 않을 경우, NullPointerException이 발생할 수 있다.
관련 Annotation
- @Configuration
- 스프링 설정 클래스로 사용하기 위한 애노테이션
- 설정 클래스를 내부적으로 스프링 빈으로 등록한다.
- AnnotationConfigApplicationContext 클래스를 이용해 스프링 컨테이너를 생성한 후 사용 가능
- @Bean
- 해당 애노테이션이 붙은 메서드에 대해 한 개의 객체만 생성한다. (싱글톤)
- 이는 다른 메서드에서, @Bean이 붙은 메서드를 메서드명을 통해 명시적으로 호출한 경우에도 동일하게 동작한다.
- 스프링은 내부적으로 설정 클래스를 상속한 새로운 설정 클래스를 만들어서 사용한다.
- @Autowired
- 스프링 설정 클래스의 필드에 @Autowired 애노테이션을 붙이면 해당 타입의 빈을 찾아서 필드에 자동으로 할당해준다.
- @Import
- 함께 사용할 설정 클래스를 지정
- 스프링 컨테이너를 생성할 때, @Import에 넣어준 설정 클래스를 지정하지 않아도 함께 컨테이너를 초기화하게 된다.
- 설정 클래스를 계층 형태로 구성함으로써, 스프링 컨테이너를 생성할 때 최상위 설정 클래스 한 개만 사용할 수 있다.
- @Qualifier
- 자동 주입 가능한 빈이 두 개 이상인 경우, 자동 주입할 빈을 지정할 수 있는 방법
- @Component
- 스프링이 직접 클래스를 검색해서 빈으로 등록할 수 있게 해준다.
- 수동 등록한 같은 이름의 빈이 존재할 경우, 수동 등록한 빈을 우선한다.
- @ComponentScan
- 설정 클래스에 지정하면 @Component 애노테이션이 붙은 클래스를 스캔해 스프링 빈으로 등록한다.
- basePackages 속성값을 통해 스캔 대상 패키지 목록을 지정할 수 있다
- excludeFilters 속성값을 통해 스캔할 때 특정 대상을 자동 등록 대상에서 제외할 수 있다.
- 다른 스캔 대상들
- @Component, @Controller, @Service, @Repository, @Aspect, @Configuration