상세 컨텐츠

본문 제목

[스프링2] 5장. 컴포넌트 스캔

22-23/22-23 Spring 2

by YUZ 유즈 2022. 10. 13. 10:01

본문

728x90

이 장의 키워드

# 컴포넌트 스캔, 왜 사용하는가?

# 기본 스캔 대상: @Component

# 컴포넌트 스캔 사용법

# 스캔 대상에서 제외하기

# 스프링 빈 충돌 처리


# 컴포넌트 스캔, 왜 사용하는가?

설정 클래스에 일일이 @Bean으로 등록하지 않아도

스프링이 직접 일반 클래스 중 @Component를 검색해서 빈으로 등록해주는 기능.

=> 설정 클래스 코드(@Configuration)를 짧게 쓸 수 있다!

 

# 기본 스캔 대상: @Component

  • @Component
    아래 어노테이션들은 @Component가 포함된 어노테이션이다.
  • @Controller
  • @Service
  • @Repository
  • @Aspect
  • @Configuration

 

# 컴포넌트 스캔 사용법

@Component 애노테이션으로 스캔 대상 지정

// 일반 클래스
@Component("listPrinter")  // 이곳에 이름을 지정하지 않으면
public class  MemberListPrinter {  // 클래스 이름의 첫글자를 소문자로 바꾼 memberInfoPrinter를 이름으로 사용
	(생략)
}
// 설정 클래스
@Configuration
@ComponentScan(basePackages = {"spring"})  // 지정한 패키지와 그 하위 패키지에 속한 클래스를 스캔한다
public class AppCtx {
    @Bean
    public MemberPrinter printer() {  // 한정자: printer
        return new MemberPrinter();
    }

    @Bean
    @Qualifier("mprinter")  // 한정자: mprinter
    public MemberPrinter printer2() {
        return new MemberPrinter();
    }
}
// 일반 클래스
// 빈을 가져올 때
ctx.getBean("빈 이름", 클래스명.class)

 

 

# 스캔 대상에서 제외하거나 포함하기

excludeFilters 속성

사용 시 자동 등록 대상에서 제외된다.

이후로는 MemberDao 클래스를 제외하는 여러 예시를 소개한다.

 

① 타입(클래스) 이름으로 제외하기

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Filtertype;
import org.springframework.context.annotation.ComponentScan.Filter;

@Configuration
@ComponentScan(basePackages = {"spring"},
	excludeFilters = @Filter(type = FilterType.REGEX, pattern = "spring\\..*Dao"))  // 여기
public class AppCtxWithExclude {
	(생략)
}
  • FilterType.REGEX
    정규 표현식을 사용해서 제외 대상을 지정한다는 것
    * 정규 표현식: 문자열을 나타내기 위한 양식
    예시) "spring\\..*Dao"  이름이 spring.으로 시작하고 Dao로 끝나는 타입
@ComponentScan(basePackages = {"spring"},
	excludeFilters = @Filter(type = FilterType.ASPECTJ, pattern = "spring.*Dao"))
  • FilterType.AspectJ
    AspectJ 패턴을 사용해서 제외 대상을 지정한다는 것
    * AspectJ 패턴: 문자열을 나타내기 위한 또다른 양식, 7장에서 계속
    예시) "spring.*Dao"  spring 패키지의 Dao로 끝나는 타입
    AspectJ 패턴을 사용하려면 pom.xml에 의존 대상으로 aspectjweaver 모듈을 추가해야 한다.
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>

② 특정 애노테이션을 붙인 타입을 제외하기

@ComponentScan(basePackages = {"spring"},
	excludeFilters = @Filter(type = FilterType.ANNOTATION,
    				classes = {NoProduct.class, ManualBean.class} ))

@NoProduct

@ManualBean

 

③ 특정 타입이나 그 하위 타입을 제외하기

배열을 이용하여 여러 개 지정할 수도 있다.

classes = [ AAA.class, BBB.class ]

@ComponentScan(basePackages = {"spring"},
	excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE,
    				classes = MemberDao.class ))

 

# 컴포넌트 스캔에 따른 충돌 처리

① 서로 다른 타입의 빈이 동일한 이름을 사용할 경우

ConflictingBeanDefinitionException 발생

 

② 일반 클래스에 @Component를 사용한 상태에서 (자동 방식)

설정 클래스에서 @Bean으로 같은 타입의 객체를 수동등록하려는 경우

  • 수동 등록한 빈이 우선된다.
  • 다른 이름을 사용하면 빈이 여러 개 존재할 수 있으며,
    @Qualifier 애노테이션 등으로 한정자를 지정하고, 사용 시 알맞은 빈을 선택해야 한다.

 


Quiz.

1. 컴포넌트 스캔은 설정 클래스에 일일이 @Bean으로 등록하지 않아도 스프링이 직접 일반 클래스 중 (컴포넌트, @Component) 어노테이션을 붙인 클래스를 검색해서 빈으로 등록해주는 기능이다.

2. 기본으로 등록되는 어노테이션으로는 (                                                      ) 6가지가 있다.

3. 위 어노테이션들은 모두 (@Component) 어노테이션을 포함하고 있다.

4. (excludeFilters) 속성 사용 시 자동 등록 대상에서 제외할 수 있다.

5. 위 속성을 사용해서 제외하는 방식 3가지: (정규 표현식), (특정 애노테이션), (특정 타입이나 그 하위 타입(클래스))

6. 스프링 설정 파일에서 자동 스캔을 위해 (@ComponentScan) 어노테이션을 사용한 상태에서, (  @Bean    ) 어노테이션으로 같은 타입의 객체를 수동 등록하려는 경우 (수동 등록)한 빈이 우선된다.

7. (다른 이름)을 사용하여 같은 타입의 빈이 여러 개 존재할 수 있으며, 사용 시 알맞은 빈을 선택해야 한다.

 

 


Corner Spring #2

Editor : 유즈

728x90

관련글 더보기