의존관계 주입 방법은 4가지가 존재합니다.
생성자를 통해서 의존 관계를 주입 받는 방법입니다.
@Component
로 등록된 클래스에서 생성자에@Autowired
애너테이션을 추가합니다.
생략 가능
Setter 메서드의 매개변수로 의존 객체를 주입하는 방법입니다.
set필드명(주입 객체)
형식의 메서드로 의존관계를 주입합니다.@Autowired
를 필수적으로 입력하여야 의존주입이 됩니다.@Autowired
public void set클래스명(클래스명 객체명){
this.객체명 = 객체명;
}
필드에 @Autowired를 붙여서 바로 주입합니다.
일반 메서드를 사용해 의존을 주입합니다.
의존 주입시 주입 하려는 객체가 스프링 컨테이너에 존재하지 않는 다면 어떻게 될 까요?
기본설정으로는 에러가 발생하며 실행을 멈춥니다. 하지만 만약 의존 객체가 존재하지 않더라도, 계속 진행하고 싶거나 다른 값을 주입하고 싶을땐 옵션을 이용하여 처리합니다.
옵션 | 설명 |
---|---|
@Autowired(required=false) | 주입할 대상 객체가 존재하지 않으면 메서드를 호출하지 않습니다. |
@Nullable | 주입할 대상 객체가 존재하지 않으면 Null 이 입력됩니다. |
Optional<> | 주입할 대상 객체가 존재하지 않으면 Optional.empy 가 입력됩니다. |
과거에는 수정자, 피드 주입을 많이 사용하였지만, 최근에는 대부분 생성자 주입을 많이 사용하고 권장하고 있습니다.
불변
: 생성되고 종료될 때까지 누군가 고의든 아니든 변경하는 것은 좋은 방법이 아니므로 생성시 최초 1회만 호출되도록 합니다.누락
: 수정자, 필드와는 다르게 생성자에서는 NullPointerException
발생시 에러를 발생시킵니다.final
: 생성자는 객체 생성시 최초 1회만 호출되므로 상수를 지정할 수 있습니다. 다른 메서드들에서는 final
상수 변경이 불가능합니다.순환 참조
: 순환참조(참조했던 객체를 다시 참조)를 방지 할 수 있습니다. 생성자 주입에서는 참조간 순환이 발생할 시 BeanCurrentlyInCreationException
에러를 발생시켜 미리 예방할 수 있습니다.
@ComponentScan
은 스프링 설정 정보 없이 자동으로 빈 객체를 등록하는 기능을 제공합니다.
지금까지는 @Configuration
애너테이션이 지정된 설정 정보 클래스에 @Bean
애너테이션이 지정된 메서드를 호출하여 스프링 컨테이너에 빈 객체를 추가하였지만, 스프링의 사이즈가 커지면 누락되는 빈 객체가 발생할 수도 있으므로 자동으로 빈 객체를 등록하는 기능이 필요하게 되었습니다.
@Configuration
@ComponentScan
public class AutoAppConfig{
}
@ComponentScan
에너테이션을 사용하면 @Component
에너테이션이 붙은 클래스들을 스프링이 자동으로 스프링 컨테이너에 빈 객체로 추가하여 줍니다.
(@Configuration
애너테이션에 @Component
에너티이션도 포함되어있으므로 설정 정보 클래스도 함께 스프링 컨테이너에 빈 객체로 추가됩니다.)
@Component
: @Configuration
설정정보 클래스의 @ComponentScan
이 해당 에너테이션이 붙은 클래스를 스프링 컨테이너에 빈 객체로 추가합니다.@Autowired
: 의존성 주입에 필요한 설정 정보 대신 의존관계 자동 주입을 해주게 됩니다.@ComponentScan(basePackages="탐색을 시작할 패키지 위치")
@ComponentScan이 탐색을 시작할 패키지의 위치를 지정합니다. 해당 패키지 부터 모든 하위 패키지를 탐색합니다.
basePackages
를 지정하지 않으면 @ComponentScan
애너테이션이 위치한 패키지부터 모든 하위패키지를 탐색합니다.
스프링 부트를 사용하면 @SpringBootApplication
애너테이션을 프로젝터의 시작 루트 위치에 두는 것을 추천합니다.
대상 | 설명 |
---|---|
@Component | 컴포넌트 스캔에서 사용 |
@Controller, @RestController | 스프링 MVC 및 REST 전용 컨트롤러에서 사용 |
@Service | 스프링 비즈니스 로직에서 사용 |
@Repository | 스프링 데이터 접근 계층에서 사용 |
@Configuration | 스프링 설정 정보에서 사용 |
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class))
@Filter(type = ) | 설명 |
---|---|
FilterType.ANNOTATION | 기본값이고, 애너테이션을 인식해서 동작합니다. |
FilterType.ASSIGNABLE_TYPE | 지정한 타입과 자식 타입을 인식해서 동작합니다. |
FilterType.ASPECTJ | AspectJ패턴을 사용합니다. |
FilterType.REGEX | 정규 표현식을 나타냅니다. |
FilterType.CUSTOM | 인터페이스를 구현해서 처리합니다. |
AnnotationConfigApplicationContext
객체에서 .getBeanDefinitionNames()
메서드를 호출하여 BeanDefinition 목록을 반환 받을 수 있습니다.
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
컨테이너.getBeanDefinition(빈설정이름)
메서드를 사용하여 빈 설정을 가졍올수도 있습니다.
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
BeanDefinition
의 정보에는 클래스명, 범위, 초기화 등 다양한 정보들이 있습니다.
@Configuration과 @Bean, @ComponentScan 과 @Component, @Autowired는 스프링에서 중요한 IoC, DI를 구현하기 위해서 사용되는 아주 중요한 애너테이션 들입니다. 옵션 하나하나 세세하게 알 필요까진 아직 없을 테지만 어떻게 동작되고 어떤 순서로 진행되는지는 지금 완전히 익혀둬야 할 듯 합니다.
https://github.com/ds02168/CodeStates_Spring/tree/main/section2-week3-DI2