[스프링 핵심원리 - 기본편] 섹션 6 + 다양한 의존관계 주입 방법

‎SE-OL·2022년 6월 28일
0

컴포넌트 스캔과 의존관계 자동 주입 시작하기

현재까지의 등록 방법 -> @Bean 등 설정 정보에 직접 스프링 빈 나열
-> 귀찮다 ....
=> @Autowired !!
@Component와 @Autowired를 각 필요한 위치에 넣은 코드 작성


클래스 명 사용 주의 (앞 두글자만 바꾸고 !)

의존관계 주입 시 스프링 컨테이너에서 자동으로 찾아서 주입함 !

탐색 위치와 기본 스캔 대상

  • basePacakges: 탐색할 패키지 시작 위치 지정 ( 포함 하위 패키지 모두 탐색 , 여러 시작 위치 설정 가능)
  • basePackageClasses: 지정한 클래스 패키지를 탐색 시작 위치로.
    만약 이 둘을 지정하지 않을 시 @ComponentScan이 붙은 정보 클래스 패키지가 시작위치가 된다.
    -> 사실 디폴트로 패키지 위치 지정하지 않고, 설정 정보 클래스의 위치를 프로젝트 최상단에 두는 것을 권장 (@SpringBootApplication이 시작 루트 위치에 두는 것이 관건인데 얘가 @ComponentScan 포함함)

골뱅이모음

  • @Component : 컴포넌트 스캔에서 사용
  • @Controlller : 스프링 MVC 컨트롤러에서 사용
  • @Service : 스프링 비즈니스 로직에서 사용
  • @Repository : 스프링 데이터 접근 계층에서 사용
  • @Configuration : 스프링 설정 정보에서 사용
  • @Controller : 스프링 MVC 컨트롤러로 인식
  • @Repository : 스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환해
  • @Configuration : 앞서 보았듯이 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리
  • @Service : 비즈니스 계층 인식에 도움

필터

  • includeFilters : 컴포넌트 스캔 대상을 추가로 지정
  • excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyExcludeComponent { //혹은 MyIncludeComponent 형식
}
package hello.core.filter;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.context.annotation.ComponentScan.Filter;

public class ComponentFilterAppConfigTest {
    @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 {
    }
}

필터 옵션

  • ANNOTATION: 기본값, 애노테이션을 인식해서 동작
    ex) org.example.SomeAnnotation
  • ASSIGNABLE_TYPE: 지정한 타입과 자식 타입을 인식해서 동작
    ex) org.example.SomeClass
  • ASPECTJ: AspectJ 패턴 사용
    ex) org.example..*Service+
  • REGEX: 정규 표현식
    ex) org.example.Default.*
  • CUSTOM: TypeFilter 이라는 인터페이스를 구현해서 처리
    ex) org.example.MyTypeFilter

중복 등록과 충돌

같은 빈 이름을 등록한다면 ??
1. 자동 vs 자동
재 등록 -> ConflictingBeanDefinitionException 예외 발생
2. 수동 vs 자동
수동 빈 등록이 우선권
Overriding bean definition for bean 'memoryMemberRepository' with a different
definition: replacing

ㄴ 로그 내용
로그의 내용을 보고 어떤 오류인지 확인할 수 있음.

다양한 의존관계 주입 방법

의존관계 주입 방법

  • 생성자 주입
  • 수정자 주입(setter 주입)
  • 필드 주입
  • 일반 메서드 주입
    생성자 주입
    생성자를 통해서 의존 관계를 주입 받는 방법 (현 우리가 사용하는 방법)
  • 생성자 호출시점에 딱 1번만 호출되는 것이 보장
  • 불변, 필수 의존관계에 사용 -> 공연때 배우를 바꾸지 않는 그런 상황

수정자 주입(setter 주입)
setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법

  • 선택, 변경 가능성이 있는 의존관계에 사용
  • 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법

필드 주입
필드에 바로 주입

  • 코드가 간결해서 많은 개발자들을 유혹하지만 외부에서 변경이 불가능해서 테스트 하기 개힘듬.
  • DI 프레임워크가 없으면 아무것도 할 수 없다.
    => 사용하지 말자!
  • 애플리케이션의 실제 코드와 관계 없는 테스트 코드
  • 스프링 설정을 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용

일반 메서드 주입
일반 메서드를 통해서 주입 받기

  • 한 번에 여러 필드 주입 받기 가능
    but, 잘 사용 안 함

0개의 댓글