해당 내용은 '스프링 입문을 위한 자바 객체 지향의 원리와 이해'와 인프런 김영한님의 '스프링 핵심 원리 - 기본편' 강의를 참고하였습니다.
@ComponentScan이란, @Component
라는 어노테이션이 붙은 클래스들을 스캔해서 자동으로 스프링 빈으로 등록해주는 어노테이션이다.
참고 :
@Component
가 이미 붙어있는 다른 어노테이션들이 있는데,
이를 유의해서 사용하도록 하자.
@Configuration
@Controller
@Service
@Repository
자 그러면 기존에 우리가 사용했던 ApplicationConfig.java
파일대신에 새로운 파일(AutoApplicationConfig.java
)을 만들어서 다음과 같이 @ComponentScan
을 어노테이션을 추가해준다.
대신 다른 점이라면 클래스 내부에 아무것도 없는 상태이다.
@Configuration
@ComponentScan
public class AutoApplicationConfig {
}
그 다음에는 ApplicationConfig 에서 사용한 구체화 클래스에 다음과 같이 @Component
와 그 생성자에 @Autowired
를 붙여준다.
@Component
public class CarImpl implements Car {
// private final FuelTank fuelTank = new GasolineOil();
// private final FuelTank fuelTank = new ElectricBattery();
private final FuelTank fuelTank;
@Autowired
public CarImpl(FuelTank fuelTank) {
this.fuelTank = fuelTank;
}
@Override
public Energy runEngine() {
return fuelTank.getEnergy();
}
// for Test
public FuelTank getFuelTank() {
return fuelTank;
}
}
위와 같이 클래스에 @Component
를 붙이면 @ComponentScan
을 통해 스캔되어 스프링 빈으로 자동 등록되어진다.
이때 스프링 빈의 기본 이름은 클래스명을 사용하되, 맨 앞글자만 소문자로 사용한다.
빈 이름 기본 전략 : 앞글자만 소문자로 해서 등록
빈 이름 직접 지정 :@Component("~~~")
로 직접 부여
이렇게 빈이 자동등록이 된다면 그 전에 ApplicationConfig에 우리가 적어놓은 @Bean
으로 작성해놓은 것들은 어떻게 되는걸까?
따로 configuration 파일에 의존성 주입을 명시하지 않는데, 어떻게 해당 클래스 생성자에 의존성을 주입할 수 있을까?
그래서 우리는 자동으로 의존성 주입이 해주는 어노테이션인 @Autowired
를 생성자에 사용한다. 빈이 자동등록이 되기에, 의존성 주입(DI)도 이제 해당 클래스안에서 해결하는 것이다.
참고 : 주입해야하는 의존성이 여러개라도 알아서 주입해준다.(타입 기반으로)
자 그럼 이론대로 우리가 @ComponentScan
을 통해서 등록한 CarImpl
이 우리가 알던 그 CarImpl
인지 확인해보자.
@Test
void scan(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoApplicationConfig.class);
CarImpl carImpl = ac.getBean(CarImpl.class);
assertThat(carImpl).isInstanceOf(CarImpl.class);
}
결과는 true로 같다는 것을 알 수 있다.