ComponentScan / 의존관계 자동 주입

mark1106·2024년 3월 19일
0

스프링

목록 보기
3/5
post-thumbnail

@ComponentScan 등장 배경

아래와 같이 클래스에 @Configuration, 메서드에 @Bean을 붙여 수동으로 스프링 빈으로 등록하고 의존 관계를 설정해 줄 수 있지만 등록해야 할 Bean이 많아질 경우 번거로움

ComponentScan을 활용하여 이 문제를 해결!

ComponentScan 이란?
컴포넌트 스캔이란 스프링이 스프링 빈(Bean)으로 등록될 준비가 된 클래스들을 스캔하여 자동으로 빈(Bean)으로 등록해주는 과정을 말한다. 

컴포넌트 스캔을 사용하려면 설정 정보 클래스에 @ComponentScan 어노테이션을 붙여 사용한다.

ComponentScan의 범위


이 때 컴포넌트 스캔의 범위는 설정 정보 클래스 패키지를 포함한 모든 하위 패키지가 된다.

ComponentScan의 기본 스캔 대상

  • @Component : 컴포넌트 스캔의 대상이 됨
  • @Controller : 스프링 MVC 컨트롤러로 인식
  • @Service : 특별한 처리 x, 비즈니스 로직이 있구나 인식만
  • @Repository : 스프링 데이터 접근 계층으로 인식, 데이터 계층의 예외를 스프링 예외로 변환
  • @Configuration : 스프링 빈이 싱글톤을 유지하도록 추가 처리

→ @Controller, @Service, @Repository, @Configuration은 @Component를 포함하고 있음

ComponentScan의 대상이 될뿐더러 추가 기능을 수행하고 어떤 역할인지 나타내준다!

ComponentScan 범위 지정1

basePackages를 활용하여 범위를 직접 지정할 수 있다. 이 때는 hello.core 패키지와 그 하위 패키지를 탐색한다.

ComponentScan 범위 지정2

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

권장 방법 : 패키지 위치 지정 x, 설정 정보 클래스의 위치를 프로젝트 최상단에 둔다!!

의존관계 주입

빈 수동 등록은 @Bean을 붙이고 직접 의존 관계를 명시해줬다. 하지만 빈 자동 등록에서는 @Autowired로 의존 관계를 주입해준다.
의존 관계 주입 방법은 다음과 같은 방법이 있다.

1. ⭐⭐생성자 주입(빈 등록 + 의존관계 주입 동시)

@Component
public class MemberService{

	 private final MemberRepository memberRepository;
	 
	 @Autowired
	 public MemberService(MemberRepository memberRepository){
		 this.memberRepository = memberRepository
	 }
}
  • 생성자 호출 시점에 딱 1번 호출(불변, 필수 의존 관계에 사용)
  • 순수한 자바 테스트에 용이
  • 필드를 final로 선언하면 초기에 값을 할당해줘야 하는데 실수로 생성자 주입 시 값 누락할 경우 컴파일 단계에서 오류를 막아줄 수 있음

2. ⭐수정자 주입(setter 주입)

@Component
public class MemberService{

	 private final MemberRepository memberRepository;
	 
	 @Autowired
	 public void setMemberRepository(MemberRepository memberRepository){
		 this.memberRepository = memberRepository
	 }
}
  • 선택, 변경 가능성이 있는 의존 관계에서 사용

3. ❌필드 주입

@Component
public class MemberService{

	 @Autowired
	 private final MemberRepository memberRepository;
	
}
  • 코드가 간결하지만 외부에서 변경이 불가능해서 테스트하기 어려움 -> 사용 x

4. ❌일반 메서드 주입

@Component
public class MemberService{

	 private final MemberRepository memberRepository;
	 
	 @Autowired
	 public void init(MemberRepository memberRepository){
		 this.memberRepository = memberRepository
	 }
}
  • 한번에 여러 필드 주입 받을 수 있음 -> 사용 x

결론

항상 생성자 주입을 사용하고 가끔 옵션이 필요한 경우 수정자 주입을 선택

롬복 사용하기

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;


    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = rateDiscountPolicy;
    }
}

다음과 같은 코드를 롬복을 사용해서 간단하게 해보자

간략화 버전1

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;


    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = rateDiscountPolicy;
    }

}
  • 생성자가 1개라면 @Autowired 생략 가능

간략화 버전2

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
 	private final MemberRepository memberRepository;
	private final DiscountPolicy discountPolicy;
}
  • @RequiredArgsConstructor : final이 붙은 필드의 생성자를 자동으로 만들어줌

즉 필드에 final을 붙이고 @RequiredArgsConstructor을 사용하자!

자동, 수동 빈 사용법

업무 로직 빈(자동) : Controller, Service, Repository 같이 유사한 패턴의 경우 자동 빈 등록

기술 지원 빈(수동) : 기술적 문제나, AOP(공통 관심사)처리, 데이터베이스 연결 등 → 설정 정보들을 한번에 관리하므로 오류 찾기 쉽고 유지 보수 용이

@Configuration
public class DiscountPolicyConfig {
 
   @Bean
   public DiscountPolicy rateDiscountPolicy() {
   		return new RateDiscountPolicy();
   }
   
   @Bean
   public DiscountPolicy fixDiscountPolicy() {
   		return new FixDiscountPolicy();
   }
}

DiscountPolicy처럼 다형성을 활용하는 비즈니스 로직은 수동 등록 고민! → 한 눈에 파악하기 위함

📚 참고

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

profile
뒤돌아보면 남는 것은 사진, 그리고 기록 뿐

0개의 댓글