Spring 5th Step

최보현·2022년 7월 12일
0

Spring

목록 보기
7/10
post-thumbnail

인프런 김영한 강사님의 스프링 핵심 원리 - 기본편 sec06

출처 : 스프링 핵심원리 - 기본편

📥컴포넌트 스캔과 의존관계 자동 주입

스프링 빈에 일일히 @Bean을 붙이는 것은 굉장히 귀찮기도 하지만, 오류가 발생할 가능성 상승
해결 방법 : 컴포넌트 스캔, @Autowired

🔍컴포넌트 스캔

@Configuration
@ComponentScan(
        excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
)
public class AutoAppConfig {
}
  • 설정 정보가 없어도 자동으로 스프링 빈 등록 '@ComponentScan'을 설정 정보에 붙여 줘야 함
  • @Configuration이 붙은 설정 정보도 자동으로 등록 됨(@Component가 있기 때문에, excludeFilters 기능을 사용하는 것이 좋음)
  • @Component 가 붙은 클래스를 스캔해서 스프링 빈으로 등록
  • 스프링 빈의 기본 이름은 클래스명을 사용하되 맨 앞글자만 소문자

🤖@Autowired

  • 의존관계 자동 주입(생성자에서 여러 의존 관계도 한 번에 가능)
  • 생성자에 @Autowired를 지정하면, 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 주입
  • 기본 조회 전략은 타입이 같은 빈을 찾아서 주입 (=getBean(MemberRepository.class)

🗺️탐색 위치와 기본 스캔 대상

모든 클래스를 다 컴포넌트 스캔하면 시간이 오래 걸림 => 꼭 필요한 위치부터 탐색하도록 시작 위치 지정

basePackages

  • 탐색할 패키지의 시작 위치를 지정
  • 지정된 패키지를 포함해서 하위 패키지를 모두 탐색
  • {패키지명, 패키지명}을 통해 여러 시작 위치 지정 가능

basePackageClasses

  • 지정한 클래스의 패키지를 탐색 시작 위치로 지정
  • 지정하지 않으면 @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치가 됨

👍🏻추천 방법!

설정 정보 클래스의 위치를 프로젝트 최상단에 두자!
=> 프로젝트의 모든 패키지들이 자동으로 컴포넌트 스캔의 대상이 됨

  • 스프링 부트를 사용하면 대표 시작 정보인 @SpringBootApplication를 프로젝트 시작 루트 위치에 두는 것이 관례! (설정 안에 @ComponentScan이 들어 있음)

컴포넌트 스캔 기본 대상

@Component : 컴포넌트 스캔에서 사용
@Controller : 스프링 MVC 컨트롤러에서 사용 / 스프링 MVC 컨트롤러로 인식
@Service : 스프링 비즈니스 로직에서 사용 / 핵심 비즈니스 로직이 여기에 있겠구나 라고 비즈니스 계층을 인식하는데 도움이 됨
@Repository : 스프링 데이터 접근 계층에서 사용 / 스프링 데이터 접근 계층으로 인식, 데이터 계층의 예외를 스프링 예외로 변환해줌
@Configuration : 스프링 설정 정보에서 사용 / 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리함

🗑️필터

includeFilters : 컴포넌트 스캔 대상을 추가로 지정
excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정

@Test
    void filterScan() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
        BeanA beanA = ac.getBean("beanA", BeanA.class);
        assertThat(beanA).isNotNull();
        Assertions.assertThrows(
                NoSuchBeanDefinitionException.class,
                () -> ac.getBean("beanB", BeanB.class));
    }

    @Configuration
    @ComponentScan(
            includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
            excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class)
    )
    static class ComponentFilterAppConfig {
    }

FilterType 옵션

  • ANNOTATION : 기본값, 어노테이션을 인식해서 동작함
  • ASSIGNABLE_TYPE : 지정한 타입과 자식 타입을 인식해서 동작함
  • ASPECTJ : AspectJ 패턴 사용
  • REGEX : 정규 표현식
  • CUSTOM : TypeFilter이라는 인터페이스를 구현해서 처리

☄️중복 등록과 충돌

같은 빈 이름이 등록되어 충돌이 되는 경우가 있다.
1. 자동 빈 등록 VS 자동 빈 등록
-> ConflictBeanDefinitionException 예외 발생
2. 수동 빈 등록 VS 자동 빈 등록
-> 수동 빈 등록이 우선권을 가짐

스프링에서 이가 오버라딩 되었다고 알려주지만, 의도를 가지고 하지 않는 이상 최대한 안 하는 것이 좋음

profile
Novice Developer's Blog

0개의 댓글