영호
[Spring] 컴포넌트 스캔 본문
우선 Spring의 특징
Spring은 객체지향의 장점을 살릴 수 있도록 도와줍니다. 객체지향 프레임워크는 객체들의 집합으로 객체들 간의 협력을 통해 기능을 완성시키기 때문에, 객체 간 의존관계를 잘 관리해야 합니다.
그렇다면, Spring에서는 어떤 식으로 객체들을 관리하는지 알아보겠습니다. 우선, Spring에서는 이러한 객체들을 빈(bean)이라는 개념으로 표현합니다. 스프링 컨테이너에 빈들을 등록하고 관리하는 방식입니다.
빈을 등록하는 방법에는 @Bean, 컴포넌트 스캔을 활용하는 방법 2가지가 있습니다. 이 2가지 방법을 비교해 보겠습니다.
@Bean
@Configuration
public class ApplicationConfig {
@Bean
public ARepo aRepo() {
return new ARepo();
}
@Bean
public AService aService() {
return new AService(new ARepo());
}
}
객체 관리를 담당하는 클래스를 생성한 뒤 @Configuration어노테이션을 작성합니다.
이후 스프링 컨터이너에서 관리하고 싶은 빈들의 생성, 의존관계 주입을 수행하는 메서드를 작성하면서 위에 @Bean어노테이션을 작성해 줍니다.
aRepo() 메서드의 경우 스프링 컨테이너에 "aRepo : 객체" 형태로 key에는 return type의 앞 글자만 소문자로 바꾼 String이 설정되고, value는 해당 객체가 할당되어 스프링 컨테이너에 등록됩니다.
aService()처럼 의존관계를 설정할 수도 있습니다.
컴포넌트 스캔
위 방법처럼 수동으로 모든 객체를 생성하고 의존관계를 주입한다면 양도 많아지고, 이 과정에서 분명 실수도 나올 것입니다. 그래서 이러한 작업들을 Spring에서는 컴포넌트 스캔을 통해 개발자가 어노테이션만 적절하게 작성하면 빈 생성, 의존관계 주입을 자동으로 해줍니다.
@Configuration
@ComponentScan
public class ApplicationConfig {
}
@Configuration, @ComponentScan을 같이 사용하게 되면 해당 클래스를 통해 모든 빈 생성, 의존관계 주입이 완료됩니다.
컴포넌트 스캔 동작 방식
Spring은 @ComponentScan이 작성된 클래스가 존재하는 패키지 하위에 존재하는 모든 클래스 파일 중 @Component어노테이션이 붙은 객체들을 모두 스프링 컨테이너에 빈으로 등록합니다.
이렇게 빈 등록이 끝나면 Spring은 @Autowired를 통해 의존관계 주입을 시작합니다.
@Controller, @Service, @Repository, @Configuration을 타고 들어가면 @Component가 붙어있는 것을 볼 수 있습니다. 그래서 해당 어노테이션도 컴포넌트 스캔의 대상이 됩니다.
주의점
이 과정에서 아래 코드처럼 스프링 컨테이너에 등록되는 key값을 설정할 수 있습니다. 만약 key값이 중복되는 빈들이 있다면 예외가 발생하니 조심해야 합니다.
public class A {
}
@Component
public class B {
}
@Configuration
@ComponentScan
public class TestConfig {
@Bean(name = "b")
public A a() {
return new A();
}
}
현재 A를 @Bean(name = "b")를 통해 b를 key값으로 스프링 컨테이너에 등록했고, @Component를 통해 B를 등록하는 과정에서 b로 변환되어 스프링 컨테이너에 빈이 등록됩니다.
이 상황에서 Spring을 동작하면 에러가 발생하고 아래와 같은 설명이 나옵니다.
The bean 'b', defined in class path resource [클래스 파일 존재 경로], could not be registered. A bean with that name has already been defined in file [클래스 파일 존재 경로] and overriding is disabled.
그렇기 때문에 b라는 key값이 중복이 되어 에러가 발생한 것입니다.
'Spring' 카테고리의 다른 글
ResponseEntity의 created(URI)는 뭘까? (feat.httpCode 201) (0) | 2023.04.24 |
---|---|
공식문서로 알아보는 IoC container (0) | 2023.04.20 |
Jdbc와 Jdbc template비교 (0) | 2023.04.20 |
[Spring JDBC] SimpleJdbcInsert로 쉽게 INSERT하기 (0) | 2023.04.12 |
[Spring] BeanFactory, ApplicationContext (0) | 2022.12.23 |