컴포넌트 스캔과 의존관계 자동 주입
설정 정보없이 자동 스프링 빈 등록하는 @ComponentScan(어노테이션 붙은 클래스찾아 빈등록)
의존관계도 자동으로 주입하는 @Autowired
-@Bean 사용
직접 설정정보,의존관계 명시
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
-@ComponentScan + @Autowired 사용
@Service
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Autowired //MemberRepository타입 맞는 스프링빈 주입
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
테스트
@Test
void basicScan() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
MemberService memberService = ac.getBean(MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
@ComponentScan, @Autowired 동작 방식

@ComponentScan 은 @어노테이션 붙은 모든 클래스 스프링 빈으로 등록(빈이름 소문자 클래스명)
이름 지정하고싶다면 @Component("memberService2")

생성자에 @Autowired 지정시, 스프링 컨테이너가 자동으로 타입이 같거나 구현한 해당 스프링 빈을 찾아 주입
getBean(MemberRepository.class) 와 동일
탐색 위치와 기본 스캔 대상
탐색 패키지의 시작 위치 지정
모든 자바 클래스 다 스캔 하려면 시간이 오래 걸리는데 꼭 필여한 위치부터 탐색하도고 시작 위치 지정 가능
@ComponentScan(basePackages = "hello.core",)
basePackages : 탐색할 패키지의 시작 위치를 지정
지정 하지 않을 시 @ComponentScan이 붙은 설정 정보 클래스의 패키지가 시작 위치
-권장 방법
위치 지정 없이 설정 정보 클래스 프로젝트의 최상단에 둘것
근데 대게 @SpringBootApplication를 프로젝트 시작 루트 위치에 두는 것이 관례(이설정안에 @ComponentScan이 있음)
컴포넌트 스캔 기본 대상
@Component : 컴포넌트 스캔에서 사용
@Controller : 스프링 MVC 컨트롤러에서 사용 /
@Service : 스프링 비즈니스 로직에서 사용
@Repository : 스프링 데이터 접근 계층에서 사용 / 데이터 계층의 예외를 스프링 예외로 변환해줌
@Configuration : 스프링 설정 정보에서 사용 / 빈 싱글톤 유지하도록 추가 처리
필터
includeFilters : 컴포넌트 스캔 대상을 추가 지정(@Component로 충분. 쓸일 없음)
excludeFilters : 컴포넌트 스캔 제외 대상 지정 (간혹 있지만 거의 안씀)
-컴포넌트 스캔 대상에 추가할 My.애노테이션
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyIncludeComponent {
}
-컴포넌트 스캔 대상에 제외할 My.어노테이션
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyExcludeComponent {
}
-컴포넌트 스캔 대상에 추가할 클래스
@MyIncludeComponent
public class BeanA {
}
-컴포넌트 스캔 대상에서 제외할 클래스
@MyExcludeComponent
public class BeanB {
}
설정
@Configuration
@ComponentScan(
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyExcludeComponent.class)
)
FilterType 옵션
- 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 자동 빈 등록 ➡︎ 수동 빈 우선권 가짐 (수동빈이 자동빈 오버라이딩함)
@Component //자동빈
public class MemoryMemberRepository implements MemberRepository {}
@Bean(name = "memoryMemberRepository") //수동빈
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
로그
Overriding bean definition for bean 'memoryMemberRepository' with a
different definition:replacing
부트는 CoreApplication 실행시키면 충돌하면 오류 발생하도록 기본값 바꿔놓음
'Spring' 카테고리의 다른 글
| [Spring] 빈 생명주기 콜백 (0) | 2025.02.26 |
|---|---|
| [Spring] 의존관계 자동 주입 (0) | 2025.02.24 |
| [Spring] 싱글톤 컨테이너 (0) | 2025.02.19 |
| [Spring] 스프링 컨테이너와 스프링 빈 조회 (0) | 2025.02.14 |
| [Spring] 스프링 개요, SOLID, DI 컨테이너 💡 (0) | 2025.01.31 |