-
스프링 부트 - 회원 관리 예제 실습 (자바 코드로 직접 스프링 빈 등록하기)Spring Framework 2022. 4. 8. 00:01
이전 시간에는 컴포넌트 스캔을 통해 스프링 빈을 등록했습니다.
@Service , @Repository, @Autowired 어노테이션을 활용하면 편리한데 왜 직접 스프링 빈으로 등록할까요?
실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용합니다.
하지만 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록합니다.
MemoryMemberRepository를 변경할 계획이므로 우리는 설정을 통해 스프링빈으로 등록하고 사용하면 기존의 코드를 건드리지 않고 변경할 수 있습니다.
#컨트롤러를 제외한 회원 서비스와 회원 리포지토리의 @Service, @Repository, @Autowired 어노테이션을 제거하고 진행합니다.
1. hello.hellospring.service 패키지에 SpriongConfig.java 파일을 생성합니다.
package hello.hellospring.service; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import hello.hellospring.repository.MemberRepository; import hello.hellospring.repository.MemoryMemberRepository; @Configuration public class SpringConfig { @Bean public MemberService memberService() { return new MemberService(memberRepository()); } @Bean public MemberRepository memberRepository() { return new MemoryMemberRepository(); } }
@Configuration 어노테이션을 단 클래스는 빈 설정을 담당하는 클래스가 됩니다.
@Bean 어노테이션을 통해 스프링 컨테이너에 객체를 등록합니다.
memberService와 memberRepository 를 스프링 컨테이너에 등록합니다.
memberService는 memberRepository를 인자로 필요하기 때문에 스프링 빈에 등록되어있는 MemberRepository를 MemberService에 넣어주게 됩니다.
의존성 주입(Dependency Injection) 에는 생성자 주입, 필드 주입, setter 주입 방법이 존재합니다.
생성자 주입
private final MemberService memberService; @Autowired public MemberController(MemberService memberService) { this.memberService = memberService; }
단일 생성자의 경우 @Autowired를 생략해도 되지만 생성자가 2개 이상인 경우에는 @Autowired 어노테이션을 생략하면 안 됩니다.
객체가 생성되는 시점에 생성자를 통해 의존성을 주입합니다.
필드 주입
@Autowired private MemberService memberService;
필드에 @Autowired 어노테이션을 붙여 의존성을 주입합니다.
생성자 주입과 달리 final로 정의할 수 없습니다.
setter 주입
@Autowired public void setMemberService(MemberService memberService){ this.memberService = memberService; }
setter가 public으로 열려있어 메서드를 호출할 수 있으므로 적절하지 않음.
의존관계가 실행 중에 동적으로 변하는 경우는 거의 없어 생성자 주입이 권장됩니다.
생성자 주입이 권장되는 이유는?
1. 순환 참조 방지
객체의 의존성을 추가하다 보면 순환 참조 문제가 발생할 수 있습니다.
A -> B
B -> A
A -> B -> A -> B -> A....
운영 중에 해당 메서드가 실행되면 순환 참조로 인해 서버가 죽어버립니다.
이를 방지하기 위해 생성자 주입을 한다면 서버 자체가 구동되지 않아 바로 순환 참조를 알 수 있습니다.
2. final 선언 가능
필드 주입과 setter 주입은 필드를 final로 선언할 수 없습니다.
즉, 나중에 변경될 가능성이 있습니다.
생성자 주입의 경우에는 필드를 final로 선언할 수 있습니다.
즉, 런타임에 객체 불변성을 보장합니다.
3. 테스트 코드 작성 용이
스프링 컨테이너 도움 없이 테스트 코드를 편리하게 작성할 수 있습니다.
필드 주입이나 setter 주입으로 빈이 주입되어 있으면 Mockito를 이용해 테스트를 진행해야 하지만
생성자 주입은 단순히 원하는 객체를 생성한 뒤, 생성자를 넣어주면 됩니다.
출처
https://jackjeong.tistory.com/41
'Spring Framework' 카테고리의 다른 글
스프링 부트 - 회원 관리 예제 실습 (H2 데이터베이스 설치) (0) 2022.04.16 스프링 부트 - 회원 관리 예제 실습 (웹 MVC 개발) (0) 2022.04.11 인텔리제이로 스프링부트 시작하는 법 (0) 2022.03.24 스프링 부트 - 회원 관리 예제 실습 (컴포넌트 스캔과 자동 의존관계 설정) (0) 2022.03.23 [Error] Using tabs can lead to unpredictable result (0) 2022.03.04