이전까지는 설정 클래스에서 수동으로 빈 객체를 등록하고 사용하는 방법을 배웠다. 이번 포스트에서는 @Component와 @ComponentScan 애노테이션을 사용하여 스프링이 스캔할 대상을 설정하고 자동으로 빈을 등록하는 컴포넌트 스캔 기능에 대해 알아볼 것이다.
@Component 애노테이션을 이용한 컴포넌트 스캔
컴포넌트 스캔은 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능이다. 따라서 설정 클래스에 별도로 빈으로 등록하지 않아도 된다. 즉 설정 클래스 코드가 크게 줄어드는 장점이 있다. 클래스에 @Component 애노테이션을 붙이면 스프링이 검색해서 빈으로 등록할 수 있다. 해당 클래스를 스캔 대상으로 표시하는 것이다.
@Component
public class ExDao {
...
}
@Component("sample")
public class SampleDao{
...
}
위의 두 코드는 빈 객체로 등록할 클래스에 @Component 애노테이션을 붙인 예제이다. @Component 애노테이션이 붙음으로써 이 클래스들은 스프링에 의해 직접 빈으로 등록될 것이다.
@Component에 값을 주었는지에 따라 빈으로 등록할 때 사용할 이름이 결정된다. 첫 번째 코드는 값을 주지 않았기 때문에 클래스 이름의 첫 글자를 소문자로 바꾼 "exDao"가 빈의 이름이 된다. 두 번째 코드는 값을 주었기 때문에 주어진 값이 빈의 이름으로 사용된다.
@ComponentScan 애노테이션으로 스캔 설정
@Component 애노테이션이 붙은 클래스를 스캔해서 빈으로 등록하려면 설정 클래스에서 @ComponentScan 애노테이션을 적용해야 한다.
@Configuration
// @Component 애노테이션을 붙인 클래스를 스캔해서 빈으로 등록하도록 한다.
// basePackages 속성은 스캔 대상 패키지 목록을 지정한다. 해당 패키지와 그 하위 패키지에 속한 클래스를 스캔 대상으로 설정한다.
// 스캔 대상 중 @Component 애노테이션이 붙은 클래스의 객체를 생성해서 빈으로 등록한다.
@ComponentScan(basePackages= {"spring"})
public class AppCtx {
@Bean
@Qualifier("example")
public ExService exService(){
return new ExService();
}
@Bean
public SampleService sampleService(){
return new SampleService ();
}
}
AppCtx 설정 클래스에 @ComponentScan 애노테이션을 붙인 예제다. 애노테이션의 basePackages 속성은 스캔할 패키지의 목록을 지정한다. 쓰인 패키지와 그 하위 패키지에 속한 클래스들을 스캔 대상으로 설정하고 스캔 대상 중 @Component 애노테이션이 붙은 클래스의 객체를 생성해서 빈으로 등록한다.
@Component 애노테이션 외에도 @Controller, @Service, @Repository, @Aspect, @Configuration 애노테이션이 붙은 클래스가 스캔 대상에 포함된다. 이들은 컴포넌트 스캔 대상이 될 뿐만 아니라 스프링에서의 특수한 기능과 연관이 있는 애노테이션이다.
컴포넌트 스캔의 충돌
컴포넌트 스캔 기능을 사용해서 자동으로 빈을 등록할 때는 충돌에 주의해야 한다. 크게 빈 이름 충돌과 수동 등록에 따른 충돌이 발생할 수 있다.
빈 이름 충돌
a 패키지와 b 패키지에 ExDao클래스가 존재하고 두 클래스 모두 @Component 애노테이션을 붙인 뒤 @ComponentScan 애노테이션을 사용하면 익셉션이 발생한다. 먼저 스캔된 클래스를 exDao라는 이름으로 등록하고, 다음으로 스캔된 클래스를 등록할 때도 이름을 exDao로 등록해야 하는데 b.ExDao와 일치하지 않는 a.ExDao 타입의 빈 이름 exDao와 충돌이 난다는 메시지가 출력된다. 즉 서로 다른 타입인데 같은 빈 이름을 사용하는 경우가 있다면 둘 중 하나는 명시적으로 이름을 지정해주어야 충돌을 막을 수 있다.
수동 등록에 따른 충돌
컴포넌트 스캔 시 부여되는 빈 이름과 수동 등록한 이름이 같을 경우에는 수동 등록한 빈이 우선한다. 즉 해당 빈 객체는 설정 클래스에서 정의한 하나만 존재한다. 반면 스캔 시의 이름과 수동 등록한 이름이 다를 경우에는 두 이름 각각에 대한 빈 객체가 생성된다. 즉 같은 타입에 대해 두 개의 빈 객체가 존재하게 된다. 따라서 해당 타입의 빈을 자동 주입해서 사용할 때에는 @Qualifier 애노테이션을 이용해 이름을 지정해 주어야 한다.
참고 서적: <초보 웹 개발자를 위한 스프링 5 프로그래밍 입문>
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
Spring Framework 시리즈
'Java > [스프링 5 프로그래밍 입문]' 카테고리의 다른 글
[Spring] AOP 프로그래밍(1) - 프록시와 AOP (0) | 2021.08.10 |
---|---|
[Spring] 빈 객체의 라이프사이클과 범위 (Life Cycle & Scope of Bean) (0) | 2021.08.03 |
[Spring] 의존 자동 주입(3) - @Autowired의 필수 여부, 자동 주입과 명시적 의존 주입 (0) | 2021.07.31 |
[Spring] 의존 자동 주입(2) - 빈 이름과 한정사 (0) | 2021.07.31 |
[Spring] 의존 자동 주입(1) - @Autowired 애노테이션 (0) | 2021.07.30 |
댓글