Spring ComponentScan과 Component
Component Sacn
-
지금까지 빈을 등록하기 위해서 AppConfig class에 사용자가 일일히 @Bean으로 관리해주어야 했습니다. 하지만 이건 개발자에게 너무 귀찮은 작업이고 누락하게 되면 큰 장애가 발생하게됩니다. 그래서 Spring은 @Bean으로 일일히 등록하지 않아도 자동으로 스프링 빈으로 등록해주는 @ComponentScan과 @Component annotation을 제공합니다.
-
컴포넌트 스캔을 사용하게 되면 DI가 애매해집니다. 지금까진 수동으로 의존관계를 주입했지만 Bean이 자동으로 등록되게되니 의존관계를 설정할 수 있는 부분이 사라진것입니다. 그래서 @Autowired annotation을 지원한다. @Autowired에 대한 부분은 다음에 공부해보겠습니다.
-
Component Scan 적용해보기 기존의 AppConfig처럼 @Bean으로 등록하고 DI를 설정할 필요도 없이 끝났습니다. ㅎㅎ @ComponentSacn으로만 끝난거지만 만약 저와 같은 예제를 작성중이신 분들은 excludeFilters를 꼭 입력해주셔야하는데요. 그 이유는 우리가 이미 AppConfig라는 스프링 컨테이너를 하나 더 만들어놨기 때문에 동시에 등록이 되지 않도록 설정해주는 것입니다.
@Configuration
@ComponentScan(
//우리가 이미 등록해놓은 AppConfig를 등록하지 않도록
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Configuration.class)
)
public class AutoAppConfig { }
-
AppConfig와 같은 위치에 AutoAppConfig class를 만들고 다음과 같이 설정합니다.
-
Component 적용해보기우리가 빈으로 관리했던 class들에게 @Component를 붙여주면 @ComponentScan이 알아서 스프링 컨테이너에 모두 등록해줍니다! 그리고 여기서 컨테이너에 등록할때 빈 이름의 기본 전략이 있는데요 첫글자는 소문자로 변형한 뒤 모두 그래도 가게 됩니다. 위의 예시의 경우 MemberServiceImpl -> memberServiceImpl로 등록되어 집니다. 빈 이름을 직접 등록할 수도 있는데요 @Component("빈 이름")으로 등록해주면 @Bean으로 등록할때 이름을 변경했던것 처럼 사용하실 수 있습니다.
@Component
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
@Autowired public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
//테스트용
public MemberRepository getMemberRepository(){
return memberRepository;
}
}
-
컴포넌트 스캔 위치컴포넌트 스캔의 탐색 위치를 basePackages를 통해 지정할 수 있는 것인데요. 프로젝트 구조상 정말 필요하다면 사용하길 권장드립니다. basePackages의 default값은 @ComponentScan이 사용된 class의 package값을 default로 가지고 가기 때문에 일반적으로 또 spring boot에서 기본적으로 제공되는 프로젝트 구조가 프로젝트의 최상단으로 지정하시는걸 권장합니다.
-
@ComponentScan( basePackages = "hello.core", }
-
@Contorller, @Service, @Repository@SpringBootApplication@Service
-
여기까지 공부하시면서 프로젝트를 진행하고 계셨거나 회사에서 프로젝트를 진행하고 계신분들은 어? 우리 프로젝트는 @Component를 쓴적이 없고 @ComponentSacn도 안쓰는데 도대체 어떻게 스프링 컨테이너를 사용하고 있는거지? 우리 회사는 싱글톤으로 디자인되지 않고 객체를 무한히 생성하는건가??? 망했다 라고 생각하실 수 있는데요. 사실 그렇지 않습니다. Spring boot 프로젝트의 경우 최초 생선된 @SpringBootApplication 내부에 @ComponentScan이 들어있고 @Controller와 @Service, @Repository에는 @Component가 포함되어 있습니다.
-
Filter
- includeFilters
- 컴포넌트 스캔 대상으로 추가
- excludeFiltersincludeFilters는 @Component가 있으면 자동으로 스캔이 되니 사용할 일이 별로 없구요. excludeFilters의 경우 실무에서 가끔 사용된다고 하네요!
- 컴포넌트 스캔 대상에서 제외
- filter 사용법다음과 같이 filter에 type과 class를 지정해주시면 됩니다.
@ComponentScan(
includeFilters = @Filter(
type = FilterType.ANNOTATION,
classes = IncludeComponent.class
),
excludeFilters = @Filter(
type = FilterType.ANNOTATION,
classes = ExcludeComponent.class
)
)
- filter type 옵션
- ANNOTATION: 기본값, 애노테이션을 인식해서 동작한다.
- ASSIGNABLE_TYPE: 지정한 타입과 자식 타입을 인식해서 동작한다.
- ASPECTJ: AspectJ 패턴 사용
- REGEX: 정규 표현식
- CUSTOM: TypeFilter 이라는 인터페이스를 구현해서 처리
-
필터를 통해 컴포넌트의 스캔의 대상에 추가할수도 제외할수도 있는데요.
-
중복 등록과 충돌
- 자동 빈 등록 + 자동 빈 등록
- 수동 빈 등록 + 자동 빈 등록2번의 경우 수동빈의 등록이 우선되며 자동 빈이 overriding됩니다. spring으로만 실행하게되면 실행이 되지만 최근 spring boot의 경우 이 경우도 에러로 처리합니다. 그 이유는 이렇게 되면 설정이 꼬이게 되어서 개발자가 잡기 어려운 버그를 만들어내기 때문입니다.
- 1번의 경우 ConflictingBeanDefinitionException 예외가 발생하게 되며 빈의 이름을 수정해야합니다.
-
만약 컴포넌트 스캔에 같은 이름의 빈을 중복으로 등록하게 되면 어떻게 될까요?
지금까지 빈을 등록하기 위해서 AppConfig class에 사용자가 일일히 @Bean으로 관리해주어야 했습니다. 하지만 이건 개발자에게 너무 귀찮은 작업이고 누락하게 되면 큰 장애가 발생하게됩니다. 그래서 Spring은 @Bean으로 일일히 등록하지 않아도 자동으로 스프링 빈으로 등록해주는 @ComponentScan과 @Component annotation을 제공합니다.
컴포넌트 스캔을 사용하게 되면 DI가 애매해집니다. 지금까진 수동으로 의존관계를 주입했지만 Bean이 자동으로 등록되게되니 의존관계를 설정할 수 있는 부분이 사라진것입니다. 그래서 @Autowired annotation을 지원한다. @Autowired에 대한 부분은 다음에 공부해보겠습니다.
Component Scan 적용해보기 기존의 AppConfig처럼 @Bean으로 등록하고 DI를 설정할 필요도 없이 끝났습니다. ㅎㅎ @ComponentSacn으로만 끝난거지만 만약 저와 같은 예제를 작성중이신 분들은 excludeFilters를 꼭 입력해주셔야하는데요. 그 이유는 우리가 이미 AppConfig라는 스프링 컨테이너를 하나 더 만들어놨기 때문에 동시에 등록이 되지 않도록 설정해주는 것입니다.
@Configuration
@ComponentScan(
//우리가 이미 등록해놓은 AppConfig를 등록하지 않도록
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Configuration.class)
)
public class AutoAppConfig { }
AppConfig와 같은 위치에 AutoAppConfig class를 만들고 다음과 같이 설정합니다.
Component 적용해보기우리가 빈으로 관리했던 class들에게 @Component를 붙여주면 @ComponentScan이 알아서 스프링 컨테이너에 모두 등록해줍니다! 그리고 여기서 컨테이너에 등록할때 빈 이름의 기본 전략이 있는데요 첫글자는 소문자로 변형한 뒤 모두 그래도 가게 됩니다. 위의 예시의 경우 MemberServiceImpl -> memberServiceImpl로 등록되어 집니다. 빈 이름을 직접 등록할 수도 있는데요 @Component("빈 이름")으로 등록해주면 @Bean으로 등록할때 이름을 변경했던것 처럼 사용하실 수 있습니다.
@Component
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
@Autowired public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
//테스트용
public MemberRepository getMemberRepository(){
return memberRepository;
}
}
컴포넌트 스캔 위치컴포넌트 스캔의 탐색 위치를 basePackages를 통해 지정할 수 있는 것인데요. 프로젝트 구조상 정말 필요하다면 사용하길 권장드립니다. basePackages의 default값은 @ComponentScan이 사용된 class의 package값을 default로 가지고 가기 때문에 일반적으로 또 spring boot에서 기본적으로 제공되는 프로젝트 구조가 프로젝트의 최상단으로 지정하시는걸 권장합니다.
@ComponentScan( basePackages = "hello.core", }
@Contorller, @Service, @Repository@SpringBootApplication@Service
여기까지 공부하시면서 프로젝트를 진행하고 계셨거나 회사에서 프로젝트를 진행하고 계신분들은 어? 우리 프로젝트는 @Component를 쓴적이 없고 @ComponentSacn도 안쓰는데 도대체 어떻게 스프링 컨테이너를 사용하고 있는거지? 우리 회사는 싱글톤으로 디자인되지 않고 객체를 무한히 생성하는건가??? 망했다 라고 생각하실 수 있는데요. 사실 그렇지 않습니다. Spring boot 프로젝트의 경우 최초 생선된 @SpringBootApplication 내부에 @ComponentScan이 들어있고 @Controller와 @Service, @Repository에는 @Component가 포함되어 있습니다.
Filter
- includeFilters
- 컴포넌트 스캔 대상으로 추가
- excludeFiltersincludeFilters는 @Component가 있으면 자동으로 스캔이 되니 사용할 일이 별로 없구요. excludeFilters의 경우 실무에서 가끔 사용된다고 하네요!
- 컴포넌트 스캔 대상에서 제외
- filter 사용법다음과 같이 filter에 type과 class를 지정해주시면 됩니다.
@ComponentScan(
includeFilters = @Filter(
type = FilterType.ANNOTATION,
classes = IncludeComponent.class
),
excludeFilters = @Filter(
type = FilterType.ANNOTATION,
classes = ExcludeComponent.class
)
)
- filter type 옵션
- ANNOTATION: 기본값, 애노테이션을 인식해서 동작한다.
- ASSIGNABLE_TYPE: 지정한 타입과 자식 타입을 인식해서 동작한다.
- ASPECTJ: AspectJ 패턴 사용
- REGEX: 정규 표현식
- CUSTOM: TypeFilter 이라는 인터페이스를 구현해서 처리
필터를 통해 컴포넌트의 스캔의 대상에 추가할수도 제외할수도 있는데요.
중복 등록과 충돌
- 자동 빈 등록 + 자동 빈 등록
- 수동 빈 등록 + 자동 빈 등록2번의 경우 수동빈의 등록이 우선되며 자동 빈이 overriding됩니다. spring으로만 실행하게되면 실행이 되지만 최근 spring boot의 경우 이 경우도 에러로 처리합니다. 그 이유는 이렇게 되면 설정이 꼬이게 되어서 개발자가 잡기 어려운 버그를 만들어내기 때문입니다.
- 1번의 경우 ConflictingBeanDefinitionException 예외가 발생하게 되며 빈의 이름을 수정해야합니다.
만약 컴포넌트 스캔에 같은 이름의 빈을 중복으로 등록하게 되면 어떻게 될까요?
Author And Source
이 문제에 관하여(Spring ComponentScan과 Component), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ililil9482/Spring-ComponentScan과-Component저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)