@ComponentScan
@ComponentScan 어노테이션은 @Component 가 붙은 모든 클래스 스프링 컨테이너에 Bean으로 등록한다.
이때 @ComponentScan 가 붙은 클래스가 존재하는 패키지를 포함한 하위의 파일들을 Scan의 대상으로 한다.
클래스 상단에 @Component 어노테이션을 사용하여 기존 수동으로 하던 Config 클래스를 통한 @Bean 등록을 @Component와 @ComponentScan을 통해 자동화할 수 있다.
Bean으로 컨테이너에 등록 되었다고 해서 의존관계에 있는 멤버 변수 (MemberService에서의 MemberRepository)가 주입이 된 것은 아니다. Spring은 이 또한 @Autowired 어노테이션을 통하여 의존관계 부여를 자동화하였다.
자동 Bean 등록, 자동 의존 관계 부여 예시)
@Component
public class MemberRepository{
}
@Component
public class MemberService{
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
}
@Configuration
@ComponentScan
public class AutoConfig{
}
// -> AutoConfig의 설정 정보를 받아 사용
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoConfig.class);
위와 같이 구성하였을 때 @Component가 붙은 클래스의 정보를 모두 가져와 Bean에 등록하고
@Autowired 어노테이션을 바라보고 필요한 파라미터를 Bean 컨테이너에서 찾아 자동 의존 관계 부여해 준다.
자동 의존 관계 부여 시 조심해야 할 점은 타입과 Bean이 이름까지 같으면 BeanDefinitionException이 발생한다. 해당 부분은 다른 포스팅을 통하여 추가 정리 예정
@Autowired의 특징 : 생성자가 하나밖에 없다면 생략이 가능하다.
위 구성에서 더욱 간소화된 방법은 AutoConfig라는 클래스를 생략이 가능하다.
그 이유는 실행을 담당하는 Application 클래스의 @SpringBootApplication 어노테이션이 @ComponentScan이 포함하고 있기 때문이다.
이는 실행단이 포함되어 있는 패키지를 포함한 하위의 파일 중 @Component가 붙은 클래스를 모두 자동으로 Bean등록한다는 것이다.
@Component가 붙는 어노테이션
@Controller : MVC 컨트롤러로 인식
@RestController : @RequestBody + @Controller 컨트롤러 어노테이션을 포함하기 때문에 Component 대상
@Repository : 싱글톤으로 유지되며 데이터 접근 계층으로 인식함, 데이터 계층의 예외를 스프링의 추상화된 예외로 변환해 줌 때문에 여러 다른 DB로의 대응이 가능해진다.
@Configuration : 스프링 설정 정보로 인식, 생성자를 통해 주입되는 스프링 빈이 싱글톤을 유지하도록 추가 작업.
@Service : 추가적인 기능은 없으나 핵심 비즈니스가 이곳에 포함되며 개발자가 비즈니스 계층을 인식함.
자동 의존 관계 주입(@Autowired)의 방법
- 생성자 주입
- setter 주입
- 필드 주입
- 일반 메서드 주입
보편적으로 생성자를 통한 의존관계 주입을 사용하지만 각 방법 별 차이점을 정리해 보았다.
1. 생성자 주입
- 객체가 생성될 때 단 한 번만 호출됨으로 의존 관계를 상수(final)로 고정시킬 수 있다.
- 초기화 값을 안 받는 등의 생성자를 막아두고 반드시 받아 객체가 생성되게 함으로써 의존관계의 설정을 필수로 강제할 수 있다.
- 불변(final)과 필수라는 특징이 있어 안정적인 의존관계를 부여하는 방법(때문에 보편적)
@Component
public class OrderService{
private final MemberRepository memberRepository;
private final OrederRepository orderRepository;
@Autowired
public OrderService(MemberRepository memberRepository, OrederRepository orderRepository) {
this.memberRepository = memberRepository;
this.orderRepository = orderRepository;
}
}
`
2. Setter 주입
- 의존관계 선택과 변경에 열려있는 의존 관계 주입 방법
- 특정 상황에 의존 관계의 주입이 변경되거나 의존관계가 어떠한 결정에 의해 부여될 때는 사용할 수도 있다.
- Setter를 열어 놓았다는 건 다른 클래스에서 접근하고 해당 의존관계를 final로 불변으로 만들 수 없음을 의미
- 외부 접근, 지속적 변경이 가능하기 때문에 적절하게 조심히 사용해야 한다.
@Component
public class OrderService{
private MemberRepository memberRepository;
private OrederRepository orderRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setorderRepository(OrederRepository orderRepository) {
this.orderRepository = orderRepository;
}
}
3. 필드 주입
- Spring컨테이너가 Bean 타입을 찾아 멤버변수에 직접 부여하도록 맴버 변수에 직접 자동 주입 하는 방법
- 코드가 간결해지는 장점이 있지만 DI 컨테이너가 없이는 작동할 수가 없다(Spring 내부에서만 작동이 가능함)
- 예를 들어 순수 자바코드의 테스트를 진행할 때 해당 코드는 의존관계 부여가 불가능하다(상수의 값을 지정하지 않아 컴파일 에러가 남)
@Component
public class OrderService{
@Autowired
private final MemberRepository memberRepository;
@Autowired
private final OrederRepository orderRepository;
}
4. 일반 메서드 주입
- Setter 주입과 같은 개념, 하지만 여러 파라미터를 통해 한번에 여러 의존관계를 부여할 수 있다.
- 같은 장, 단점을 공유한다. 변경이 필요할 때 조심히 적절하게 사용해야 한다.
@Component
public class OrderService{
private MemberRepository memberRepository;
private OrederRepository orderRepository;
@Autowired
public void init(MemberRepository memberRepository , OrederRepository orderRepository) {
this.memberRepository = memberRepository;
this.orderRepository = orderRepository;
}
}
'Spring' 카테고리의 다른 글
Spring AOP / @Aspect (JoinCut와 Advice) (2) | 2024.01.12 |
---|---|
AOP의 정의와 프록시/데코레이션 패턴 (1) | 2024.01.04 |
스프링 컨테이너와 싱글톤(feat. @Configuration) (0) | 2023.12.28 |
MVC 아키텍쳐 및 SpringMVC 구조 (0) | 2023.12.26 |
제어의 역전(IoC)과 의존관계 주입(DI) (1) | 2023.12.22 |