하나씩 차근차근
article thumbnail

앞에서 스프링 빈을 등록할때 스프링 컨테이너를 @Configuration 과 @Bean 을 사용하는 방법과

XML 을 통해 만드는 방법으로 스프링 빈을 등록했습니다.

만약 등록해야할 스프링 빈이 많아지면 설정 정보가 커지고 누락하는 문제가 발생합니다.

그래서 자동으로 스프링 빈을 등록하는 컴포넌트 스캔을 사용해보겠습니다.

 

시작

컴포넌트 스캔을 사용하면 @Configuration 이 붙은 설정 정보도 등록되기 때문에

Appconfig 에 붙은 @Configuration 과 @Bean 을 지워줍니다.

 

package hello.core;

import hello.core.member.MemberRepository;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.DiscountPolicy;
import hello.core.order.FixDiscountPolicy;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import hello.core.order.RateDiscountPolicy;

public class Appconfig {
	
	public MemberRepository memberRepository() {
		return new MemoryMemberRepository();
	}
	
	public DiscountPolicy discountPolicy() {
		// return new FixDiscountPolicy();
		return new RateDiscountPolicy();
	}
	
	public OrderService orderService() {
		return new OrderServiceImpl(memberRepository(), discountPolicy());
	}
	
	public MemberService memberService() {
		return new MemberServiceImpl(memberRepository());
	}
}

다음으로 @Configuration 이 붙은 AutoAppConfig 클래스를 하나 만듭니다.

package hello.core;

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

@Configuration
@ComponentScan
public class AutoAppConfig {

}

 

컴포넌트 스캔

컴포넌트 스캔은 @Component 애노테이션이 붙은 클래스를 스프링 빈으로 등록합니다.

@Configuration 애노테이션도 @Component 애노테이션을 포함하기 때문에 스프링 빈으로 등록합니다.

다음과 같이 각각의 클래스에 @Component 를 붙여줍니다.

  • MemoryMemberRepository
  • RateDiscountPolicy
@Component
public class MemoryMemberRepository implements MemberRepository {
	...
}
@Component
public class RateDiscountPolicy implements DiscountPolicy{

}

다음 클래스에는 @Component 와 @Autowired 를 붙여줍니다.

  • MemberServicelmpl
  • OrderServicelmpl
package hello.core.member;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MemberServiceImpl implements MemberService {

	private final MemberRepository memberRepository;
	
	@Autowired
	public MemberServiceImpl(MemberRepository memberRepository) {
		// TODO Auto-generated constructor stub
		this.memberRepository = memberRepository;
	}
	...
}
package hello.core.order;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;

@Component
public class OrderServiceImpl implements OrderService{

	private final MemberRepository memberRepository;
	
	private final DiscountPolicy discountPolicy;

	@Autowired
	public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
		// TODO Auto-generated constructor stub
		this.memberRepository = memberRepository;
		this.discountPolicy = discountPolicy;
	}
	...
}

@Autowired 애노테이션은 의존관계를 주입해줍니다.

package hello.core;

import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import hello.core.member.MemberService;

public class AutoAppConfigTest {

	@Test
	void basicScan() {
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
		MemberService memberService = ac.getBean(MemberService.class);
		System.out.println("memberSerivce = " + memberService);
		System.out.println("memverService.getClass() = " + memberService.getClass());
	
	}
}

다음으로 AutoAPpConfigTest 클래스를 만들어서 등록된 빈을 타입으로 찾아확인해보면 다음과 같이 출력됩니다.

memberSerivce = hello.core.member.MemberServiceImpl@3935e9a8
memverService.getClass() = class hello.core.member.MemberServiceImpl

 

동작 순서

먼저 AutoAppConfig 클래스 파일에 붙은 @ComponentScan 은 @Component 가 붙은 모든 클래스를

스프링 빈으로 등록합니다. (이때, @Configuration 도 스프링 빈으로 등록됩니다.)

  • 빈 이름은 클래스 명의 앞글자만 소문자가 됩니다 (MemberServiceImpl.class → memberServicelmpl)
  • 빈 이름을 직접 지정하려면 @Component("memberService2") 방법 사용

다음으로 @Autowired 가 붙은 생성자에 스프링 컨테이너가 자동으로 해당 스프링 빈을 주입합니다.

 

탐색 위치와 대상

탐색 위치

기본 탐색 위치는 @ComponentScan 이 붙은 설정 정보 클래스의 패키지를 대상으로 탐색합니다.

( @ComponentScan 이 붙은 AutoAppConfig 클래스의 패키지인 hello.core 스캔 )

package hello.core;

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

@Configuration
@ComponentScan
public class AutoAppConfig {

}
프로젝트의 최상단 패키지에 @ComponentScan 이 붙은 설정 정보 클래스를 두는것을 권장

 

탐색 대상

컴포넌트 스캔의 탐색 대상은 다음과 같습니다.

  • @Component
  • @Controller : 스프링 MVC 컨트롤러로 인식
  • @Service 
  • @Repository
  • @Configuration : @Component 애노테이션을 포함하고 있음
profile

하나씩 차근차근

@jeehwan_lee

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!