JAVA & SPRING/Spring 핵심원리-기본

스프링 핵심 원리 - 5일차 (컴포넌트 스캔)

눈오는1월 2023. 7. 29. 22:59
728x90

여태까지 우리는 스프링 컨테이너에 스프링 빈을 등록할때 @Bean이나 xml(지금은 거의 안씀)을 활용해서 등록을 했는데 이번에는 자동으로 빈을 등록해주는 컴포넌트에 대해 알아본다.

hello.core 패키지에 AutoAppConfig 클래스를 만든다.

package hello.core;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

@Configuration // 설정정보
// 자동으로 스프링 빈 등록
@ComponentScan( // 참고로 어노테이션은 메타정보임
        //지정하지 않으면 해당 클래스가 있는 패키지 부터 시작(이친구부터 하위 패키지까지)
        basePackages = "hello.core.member", // 모든 클래스를 다 뒤지는건 너무 오래걸리기때문에 basePackages를 통해서 패키지 서치 시작점을 지정할 수 있음
        basePackageClasses = AutoAppConfig.class, // AutoAppConfig가 있는 클래스에 패키지부터 시작
    excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
        //Configuration 어노테이션 사용한 부분도 자동으로 빈으로 등록되기때문에 위 코드를 사용해서 기존에 만들었건거 등록 안되게끔 방지함
)
public class AutoAppConfig {

}

@ComponentScan 어노테이션은 @ComponentScan이 붙은 클래스를 스프링 빈으로 등록을 해주기에 구현 클래스에 @ComponentScan을 붙인다.

 

이때 궁금한점이 예전에 AppConfig에는 의존관계를 직접 적어줬는데 이렇게 컴포넌트 스캔을 이용하면 어떻게 할 수 있을까? -> @Autowired를 통해서 의존관계를 자동으로 주입할 수 있다. 의존관계 주입하는 생성자 부분에 @Autowired 어노테이션을 사용한다.

 

위 사진은 컴포넌트 스캔을 사용했을때 어떻게 적용이 되는지 보여주는것이다. 컴포넌트 스캔을 사용하면 @Component가 붙은 클래스를 스프링 빈에 등록을 해준다. 이때 주의할점은!! 등록할때 앞글자가 소문자로 이름을 변환해서 등록을 해준다.

( ex) MemberServiceImpl -> memberServiceImpl) 만약 이름을 직접 등록하고 싶으면 @Component("이름을 직접 등록") 해서 사용하면 된다. (보통은 그냥 붙인다.)

@Autowired를 지정하면 스프링 컨테이너가 스프링 빈을 찾아서 주입을 해준다. 그래서 파라미터가 많아도 알아서 다 자동으로 주입을 해준다.

 

위 코드 주석으로 적은 부분중에 basePackages 라고 적힌 부분이 주석처럼 모든 클래스와 라이브러리들을 다 찾기엔 너무 오래걸리므로 탐색할 패키지 시작을 지정해서 해당 패키지부터 시작해서 해당패키지의 하위 패키지만 탐색할 수 있게 해줌.

만약 지정하지 않게되면 @ComponentScan이 붙은 곳이 시작 위치가 됨

 

권장방법은 지정하지않고 설정 정보 클래스를 맨위에 둔다고한다. 

 

 

참고로 컴포넌트 스캔은 다른 어노테이션도 대상에 포함된다

@Controller(스프링 MVC 컨트롤러),

@Service(스프링 비즈니스 로직), (얘는 딱히 기능이 있다기보다 핵심 비즈니스 로직이 여기에 있겠구나 라고 개발자들이 확인하는데 도움을 줌)

@Repository(스프링 데이터 접근 계층),

@Configuration(스프링 설정 정보)

 

-> 얘네를 까보면 @Component가 붙어있음

 

추가로 어노테이션에서는 상속이라는 개념이 없음 그래서 어노테이션이 붙어있는지 확인하는건 java의 기능이 아니라 스프링의 기능이다.

 

또 필터를 통해서 컴포넌트 스캔 대상을 지정할 수 있음

includeFilters -> 컴포넌트 스캔 대상을 지정함

excludeFilters -> 컴포넌트 대상을 지정하지 않음

 

마지막으로 자동 등록과 충돌에 대해서 알아보자

빈이 충돌하는 경우에는

1. 자동 빈 등록 vs 자동 빈 등록

2. 자동 빈 등록 vs 수동 빈 등록

이렇게가 존재한다.

 

1번같은 경우에는 ConflictingBeanDefinitionException 예외 발생한다.

 

2번같은 경우에는 수동 빈이 자동 빈을 오버라이딩 한다(수동 빈 우선권을 가짐)

그래서 2번같은경우 개발자에 의도와 다르게 될경우 되게 애러를 찾기 어려워짐 그렇기에 스프링에서는 스프링이 돌아갔을때 오류를 뜨게 만들었다 CoreApplication을 돌려서 오류를 확인할 수 있다.

 

 

 

728x90