Spring
Spring Bean 과 의존관계 설정 두가지 방법
kiki1875
2024. 11. 25. 15:58
Component Scan과 자동 의존관계 설정
Spring은 기본적으로 @ComponentScan을 통해 특정 패키지와 그 하위 패키지를 스캔하여 @Component가 붙은 클래스를 Bean으로 등록한다.
@SpringBootApplication에 이미 @ComponentScan이 포함되어 있어, 별도의 설정 없이도 이러한 동작이 가능하다.
Spring Bean 등록 예시
@Controller
public class MemberController {
}
위와 같이 선언하면, Spring Container가 생성된 후 MemberController 객체를 생성하여 Spring이 관리하게 된다.
의존성 주입 예시
MemberService를 사용하려면 해당 의존성을 Spring Container에 등록하고, 주입받아야 한다.
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
위 코드에서 @Autowired 어노테이션을 사용하면, Spring이 memberService에 연결된 객체를 Spring Container에서 찾아 주입한다. 이는 이전 테스트에서 개발자가 직접 의존성을 주입하던 방식과는 대조적이다.
주의 사항
- MemberService와 MemberRepository도 Spring Container에 등록되어야 한다.
- 이를 위해 각각 @Service, @Repository 어노테이션을 선언해 주어야 한다.
- @Component 어노테이션의 역할
- @Service, @Controller, @Repository는 모두 @Component를 포함하고 있으며, 해당 클래스가 Spring Bean으로 자동 등록되도록 한다.
생성자와 @Autowired
- 생성자에 @Autowired가 있으면 객체 생성 시점에 Spring Container에서 해당 Spring Bean을 찾아 주입한다.
- 생성자가 하나일 경우 @Autowired는 생략 가능하다. Spring이 자동으로 의존성을 주입한다.
- 생성자가 여러 개일 경우, 어떤 생성자를 사용할지 명시적으로 지정하기 위해 @Autowired를 반드시 추가해야 한다.
Spring Bean 등록 시 Singleton
Spring Container에 등록된 Bean은 기본적으로 Singleton으로 관리된다. 이는 애플리케이션 전반에 걸쳐 동일한 인스턴스를 재사용하도록 보장한다.
Java 코드로 직접 스프링 Bean 등록하기
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
}
위 예시는 Spring 에서 Java Config 를 활용하여 직접 Bean을 등록하는 예시이다.
@Configuration 을 통해 해당 클래스가 설정 파일임을 명시하고, @Bean 을 통해 정의된 객체들을 Spring Bean 으로 등록 / 관리한다.
작동 원리
- Spring이 SpringConfig 클래스를 읽고, @Bean 메서드를 호출한다.
- memberService() 메서드가 호출되어 MemberService 객체가 생성되고, 이를 Spring Container에 등록한다.
- memberRepository() 메서드가 호출되어 MemberRepository 객체가 생성되고, 이를 Spring Container에 등록한다.
- memberService() 메서드 내부에서 memberRepository() 메서드를 호출하므로, 생성된 MemoryMemberRepository 객체가 MemberService의 생성자에 주입된다.
Java Config 방식의 장점
- 명시적 구성
- @ComponentScan 을 사용하는 방식에 비해, 의존성이 명시적으로 관리된다. 우리의 예시에서 MemberRepository 는 인터페이스이다. 그렇다면 어떤 MemberRepository 가 들어갈지, (MemoryMemberRepository) 를 코드에서 명시할 수 있는 것이다.
- 테스트 용이성
- Java Config 를 통해 구현체를 쉽게 교체할 수 있다. 즉, MemberRepository 의 다른 구현체로 바꾸고 싶다면, JavaConfig 의 내용만 바꾸어 주면 된다.