프로필사진

Go, Vantage point

가까운 곳을 걷지 않고 서는 먼 곳을 갈 수 없다.


Github | https://github.com/overnew/

Blog | https://everenew.tistory.com/





티스토리 뷰

반응형

 

 

 

* 김영한님의 스프링 핵심원리 기본편 강좌를 수강하며 정리한 글입니다. *

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

 

 

이전 글에서는 싱글톤 패턴과 스프링 컨테이너의 원리에 대하여 정리했다.

 

 

컴포넌트와 스캔

 

스프링 빈은 설정 정보를 @Bean으로 일일이 등록을 해주어야 한다.

이를 편리하게 자동으로 등록해주는 것이 컴포넌트 스캔이다.

 

설정 정보 클래스에 @ComponentScan 어노테이션을 추가로 붙여주면,

해당 설정 정보를 사용해 스프링 컨테이너 생성 시 모든 클래스를 대상으로 컴포넌트 스캔이 진행된다.

 

이제 클래스가 컴포넌트 스캔의 대상이 되도록 @Component 어노테이션을 추가하면 빈으로 등록된다.

하지만 설정 정보에서는 의존관계가 설정되어 있었다.

 

 

예를 들어 MemberServiceImpl를 생성할 때는 memberRepository를 컨테이너에서 자동으로 주입받았다.

@Bean
public MemberService memberService(){
	//memberRepository()를 주입받음
    return new MemberServiceImpl(memberRepository());
}

 

클래스별로 컴포넌트 등록을 한다면 DI(의존성 주입)은 어떻게 해결해야 할까?

이를 해결해 주는 것이 바로 @Autowired 어노테이션이다.

 

MemberServiceImpl의 생성자에  @Autowired를 붙여주면 스프링 생성 시 의존관계가 자동 주입된다.

@Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}

 

 

 

컨테이너가 의존관계를 주입하는 순서는 다음과 같다.

 

1.  @ComponentScan 이 붙은 설정 정보로 컨테이너 생성

new AnnotationConfigApplicationContext(AutoAppConfig.class);

2. 모든 클래스를 확인하여 @Component 가 붙은 클래스를 빈으로 등록

  이때 등록되는 빈의 이름은 class의 앞 글자만 소문자로 바꾸어 등록된다.

 ( Member -> member)

 

3. 생성자에 @AutoWired가 붙으면 스프링 컨테이너가 해당 빈을 찾아 자동으로 주입

 따라서 싱글톤이 지켜진다.

 

 

 

스캔 위치 지정과 대상

 

@ComponentScan에는 여러 옵션도 적용 가능하다.

특히 스캔 대상 패키지는 basePackages = "PATH"  또는 {"PATH1", "PATH2" ... }로 설정 가능하다.

basePackageClasses = class 는 해당 class의 패키지를 기본 탐색 위치로 설정한다.

 

@Configuration
@ComponentScan( basePackages = "hello.core.member")
// member 패키지 하위의 class만 스캔됨
public class AutoAppConfig {

}

만약 스캔 위치를 지정하지 않는다면, @ComponentScan 설정 정보 클래스의 패키지가 탐색 위치가 된다.

관례적으로 탐색 위치 설정보단, 설정 정보 클래스를 루트 패키지에 두어 사용한다.

 

 

사실, 스프링 부트를 사용한다면 @SpringBootApplication에는 @ComponentScan이 적용되어 있다.

따라서 @SpringBootApplication 이 적용된 클래스의 패키지가 자동으로 스캔 위치로 설정된다.

 

 

컴포넌트 스캔은 @Component 가 적용된 클래스를 등록하는데

@Controller, @Service, @Repository, @Configuration 에도 @Component가 적용되어 있다.

따라서 위의 어노테이션 적용 시 자동으로 스캔의 대상이 된다.

 

사실 어노테이션은 순수 자바에서는 주석의 역할(메타 정보)로 사용되지만, 위와 같은 복잡한 기능이 도대체 뭔가 생각이 들 수 있다. 이는 스프링에서 지원하는 기능으로 서로 연결하여 부가 기능을 수행해 준다.

 

 

컴포넌트 스캔 필터

 

@Configuration
@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.옵션,
    classes = 포함 시킬.class),
    excludeFilters = @ComponentScan.Filter(type = FilterType.옵션,
    classes = 배제 시킬.class)
)
static class ComponentFilterAppConfig{
}

includeFilters는 빈으로 등록시킬 클래스

excludeFilters는 빈 등록에서 배제시킬 클래스를 필터로 설정할 수 있다.

 

필터의 옵션으로는 5가 존재한다.

ANNOTATION: default 옵션으로 어노테이션을 인식

ASSIGNABLE_TYPE: 지정한 클래스 타입 인식

ASPECTJ:  AspectJ 패턴 사용

REGEX: 정규 표현식 

CUSTOM: 직접 filter 인터페이스 구현해 적용

 

하지만 기본 설정에 맞추어 진행하는 상황이 많다.

 

 

@Component("빈 이름")으로 이름 설정도 가능하다.

단, 중복된 이름이 있다면 컴포넌트 스캔 시 다음 오류가 발생한다.

ConflictingBeanDefinitionException: Annotation-specified bean name

 

하지만 @Bean과 @Component 간의 이름 중복은 수동 빈(@Bean)이 자동 빈(@Component)을 오버라이딩 하여 오류가 발생하지 않는다.

물론, 오류 발생 없이 오버라이딩이 되어 버리면 개발자는 어떤 문제가 일어났는지도 알기 힘들 것이다.

따라서 스프링 부트는 오류를 발생시키도록 변경되었다.

 

 

 

 

반응형
댓글
반응형
인기글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함