@Component와 @Autowired를 통한 컴포넌트 스캔
클래스 레벨에 @Configuration
을 붙여 스프링 컨테이너에 구성 정보를 제공하고, 각 메서드마다 @Bean
을 붙여 스프링 빈을 등록하는 방식은 등록해야 할 빈이 많아지면 효율적이지 못한 문제가 있다.
이를 해결하는 방법은 설정 정보 없이도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔 기능과 의존 관계를 자동으로 주입해주는 @Autowired
기능을 사용하는 것이다.
컴포넌트 스캔은 기존의 방식과는 다르게 @Component
가 붙은 클래스를 스캔해 스프링 빈으로 등록한다.
추가로, @Controller, @Repository, @Configuration
역시 스캔 대상에 포함하고 각각 MVC 컨트롤러, 스프링 데이터 접근 계층, 스프링 설정 정보로 인식한다. 추가로 @Service
역시 인식하는데 특별한 처리를 하지는 않고 개발자 측에서 비즈니스 계층으로 인식하는 데 도움이 된다.
대략적으로 위와 같은 프로그램을 설계한다고 가정한다.
일단 인터페이스를 구현하고 있는 실제로 사용할 클래스에 @Componet
를 붙여 컴포넌트 스캔의 대상으로 등록한다. 여기서는 MemoryMemberRepository와 FixPointPolicy 클래스를 사용한다고 가정한다.
@Component
public class MemoryMemberRepository implements MemberRepository {...}
@Component
public class FixPointPolicy implements PointPolicy {...}
이어서 MemberService와 OrderService를 구현하는 MemberServiceImpl 클래스와 OrderServiceImple 역시 @Component
를 사용해 등록하고, @Autowired
로 의존 관계를 주입한다.
@Component
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Autowired //의존 관계 자동 주입
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void register(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final PointPolicy pointPolicy;
@Autowired //의존 관계 자동 주입
public OrderServiceImpl(MemberRepository memberRepository, PointPolicy pointPolicy) {
this.memberRepository = memberRepository;
this.pointPolicy = pointPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int point = pointPolicy.point(member, itemPrice);
return new Order(memberId, itemName, itemPrice, point);
}
}
필터를 사용해 컴포넌트 스캔 대상을 지정하기
@ComonentScan
을 사용할 때 옵션으로 includeFilters
나 excludeFilters
를 사용해서 스캔에 포함하거나 제외할 클래스를 지정할 수 있다.
필터 적용을 위해 자체적으로 어노테이션을 만든다. 만든 어노테이션을 포함하거나 제외할 클래스 레벨에 붙이고, 컴포넌트 스캔 포함/제외 대상을 지정한다.
excludeFilters 사용 예
1. 어노테이션 생성
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcludeComponent {}
2. 클래스에 어노테이션 적용
@ExcludeComponent
public class ExcludeBean {}
3. @ComponentScan 시 적용
import static org.springframework.context.annotation.ComponentScan.*;
@ComponentScan(excludeFilters = @Filter(type = FilterType.ANNOTATION, classes = ExcludeBean.class)
FilterType의 옵션
ANNOTATION
기본 값으로, 어노테이션을 인식해 동작한다.
ASSIGNABLE_TYPE
지정한 타입 및 자식 타입을 인식해 동작한다.
ASPECTJ
AspectJ 패턴을 사용한다.
REGEX
정규표현식
CUSTOM
TypeFilter라는 인터페이스를 구현해서 처리한다.
'back-end > spring' 카테고리의 다른 글
spring/ 롬복lombok 사용하기 (0) | 2022.06.21 |
---|---|
spring/ 의존 관계 자동 주입 - 생성자 주입을 사용하자 (0) | 2022.06.20 |
spring/ 싱글톤 컨테이너 (0) | 2022.06.20 |
spring/ 스프링 컨테이너와 스프링 빈 (0) | 2022.06.17 |
spring/ 관심사 분리SoC, 제어의 역전IoC, 의존 관계 주입 DI (0) | 2022.06.17 |