-
Spring Boot에서 @ComponentScan을 안해도 되는 이유Spring 2024. 1. 5. 10:28
[Spring에서 @ComponentScan 사용하지 않는 경우]
원래 Spring에서는 어떤 클래스들을 @Bean으로 만들지 @Configuration 클래스에 직접 명시를 해줘야한다
@Configuration public class AppConfig { @Bean public MemberRepository memberRepository(){ return new MemoryMemberRepository(); } @Bean public MemberService memberService(){ return new MemberServiceImpl(memberRepository()); } @Bean public DiscountPolicy discountPolicy(){ return new RateDiscountPolicy(); } @Bean public OrderService orderService(){ return new OrderServiceImpl(memberRepository(),discountPolicy()); } }하지만 Spring에서 전과 같이 직접 어떤 객체가 Bean으로 등록될지 작성하지 않아도 되게 하는 어노테이션이 있는데
그게 바로 아래의 @ComponentScan이다.
[@ComponentScan의 등장]

@ComponentScan을 사용하면 다음과 같이 간단하게 AppConfig를 정의할 수 있다.
@ComponentScan을 사용한 구성정보 클래스에 아무 코드가 없어도 된다!
@Configuration @ComponentScan(excludeFilters=@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)) public class AppConfig { // componentScan 을 사용하므로 @Bean 정의를 안해도 된다 // Bean 으로 쓸 클래스에 @Component 만 붙여주면 된다 }그리고 기존에 @Bean 으로 정의함으로써 각 method 의 객체를 spring container에 bean으로 등록하는 작업은
해당 객체의 클래스에 @Component 를 붙여줌으로써 대체가능하다.
[@Autowired의 등장]
하지만 위와 같이 @ComponentScan만 사용하면 Bean 객체들을 생성해서 Spring Container에 등록만 시키지,
각 Bean들간의 의존관계를 정립시켜주지는 않는다.
즉 @ComponentScan이 의존관계 주입까지는 해주지 않는다는 것이다!
따라서 ComponentScan된 Bean 들간 알아서 의존관계 주입이 되게 만들어야하는데 그때 사용하는 것이 @Autowired이다.

생성자에 @Autowired를 지정하면, 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 주입한다.
@Component public class MyController { private final MyService myService; @Autowired public MyController(MyService myService) { this.myService = myService; // 등록된 Bean 중에서 MyService를 찾아 주입함 } }자신이 의존하고 있는, 이미 존재하는 객체를 사용해야할때 사용해주면 된다.
[@ComponentScan vs @Autowired]
1. @ComponentScan
@Component, @Service, @Repository, @Controller 같은 어노테이션이 붙은 클래스를 찾아서 Spring Container에 Bean으로 등록함.
즉, 어떤 클래스들을 Bean으로 만들지를 결정함
2. @Autowired
이미 등록된 Bean 중에서 필요한 의존성을 찾아서 주입함
즉, 어떤 Bean이 어떤 Bean을 필요로 하는지 연결하는 역할
@ComponentScan은 Bean을 등록하는 과정이고, @Autowired는 그 Bean들을 서로 연결(주입)하는 과정입니다.
[의존관계 주입은 생성자로 하는게 가장 좋다]
1. 일단 의존관계 주입은 1번 설정되면 앱이 종료할때까지 바뀌면 안되는 것이고
2. 생성자는 이러한 목적을 제대로 수행해주는 얘이고
3. 생성자로 하면 변수에 final 도 사용할 수 있어 더할 나위 없이 안정적인 환경이 구성되기 때문이다.
[SpringBoot에 @ComponentScan 과 AppConfig가 없는 이유?]
근데 Spring Boot 에서는 @ComponentScan과 AppConfig 같은 설정정보 클래스를 만들지 않아도 되는 이유가
@SpringBootApplication 이라는 어노테이션 자체가 @ComponentScan을 해주기 때문이다!
@SpringBootApplication이 어노테이션이 사실 복합 어노테이션인 것이다.
@Target(...) @Retention(...) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan public @interface SpringBootApplication { }즉, @SpringBootApplication 에는 이미 @ComponentScan이 들어가 있기 때문에
그래서 SpringBootApplicatin을 붙인 클래스 기준으로 같은 패키지 이하를 자동 스캔하게 된다.
그리고 SpringBootApplication이 된 main 클래스는 Spring Container 전체인 ApplicationContext 자체를 반환하기 때문에
현재 프로젝트의 Spring Container 내부에 있는 모든 Bean/Component 에 대한 ComponentScan 을 진행하여 스프링 컨테이너에 등록해주는 것이다!
'Spring' 카테고리의 다른 글
예외처리 (@RestControllerAdvice + @ExceptionHandler) (1) 2024.02.05 @PathVariable vs @RequestParam (0) 2024.01.28 스프링 컨테이너와 @Configuration and @Bean (1) 2024.01.05 스프링 인터셉터 (0) 2023.12.29 서블릿 필터 (0) 2023.12.28