공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.
스프링 빈을 등록하는 방법에는 2가지가 있다.
1. 컴포넌트 스캔
2. 자바 코드로 직접 빈 등록
컴포넌트 스캔과 자동 의존관계 설정
이전 시간에 만든 회원 서비스를 완성도 있게 만들려면 Controller와 view가 필요하다. (회원가입 결과를 HTML로 뿌려주기 위해)
-> 이 과정을 멤버 컨트롤러가 멤버 서비스를 의존한다 라고 표현한다.
1. MemberController를 생성한다.
package hello.hello_spring.controller;
import hello.hello_spring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
- 스프링 컨테이너가 처음 생성될 때 @Controller 애노테이션이 있으면, Spring에 Controller 객체를 생성해서 넣고 관리한다.
- 이것을 스프링 컨테이너에서 스프링 빈이 관리된다고 표현한다.
- MemberService를 new를 이용하여 객체를 생성할 수도 있다. 하지만 이렇게 되면 다른 여러 컨트롤러들이 멤버 서비스를 가져다가 사용하는 문제가 생긴다. 따라서 스프링 컨테이너에 등록하고 사용하는 것이 좋다.
- 생성자에 @AutoWired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다.
2. 여기까지 과정을 그림으로 보면 아래와 같이 표현할 수 있다.
3. 아직 memberService는 스프링 빈으로 등록되어 있지 않다.
4. MemberService도 스프링 빈에 등록해주기 위해 @Service 애노테이션을 붙여준다.
5. MemoryMemberRepository도 애노테이션을 붙여준다.
6. 이제 스프링 빈에 controller, service, repository가 등록/연결이 되었다.
7. 이러한 방식이 컴포넌트 스캔 방식이다.
-> controller, service, repository 각각의 애노테이션에는 @Componet가 선언되어 있다.
* 컴포넌트 스캔 : 스프링 컨테이너에 등록
* Autowierd : 연관관계
8. 컴포넌트 스캔 원리
- @Component 애노테이션이 있으면 스프링 빈으로 자동 등록된다.
- @Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문이다.
- @Component 를 포함하는 다음 애노테이션도 스프링 빈으로 자동 등록된다.
- @Controller
- @Service
- @Repository
9. 아무 파일에나 @Componet가 있다고 스프링 빈으로 컴포넌트 스캔이 되는 것은 아니다.
- SpringApplication의 패키지를 포함한 하위 패키지만 스캔한다.
- 즉, package hello.hello_spring 안에 있는 파일들만 스캔한다.
참고 : 스프링은 기본적으로 스프링 빈을 싱글톤으로 등록하여, 동일한 빈은 모두 같은 인스턴스를 공유한다. 특별한 경우가 아니면 대부분 싱글톤을 사용한다.
자바 코드로 직접 스프링 빈 등록하기
1. service와 repository의 애노테이션을 제거한다. (@Service, @Repository)
2. SpringConfig 클래스를 생성한다.
package hello.hello_spring;
import hello.hello_spring.repository.MemberRepository;
import hello.hello_spring.repository.MemoryMemberRepository;
import hello.hello_spring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
}
- @Configuration : 스프링 컨테이너는 @Configuration이 붙어있는 클래스를 자동으로 빈으로 등록하게 된다.
- @Bean : 수동으로 스프링 빈을 등록한다.
- memberService()와 memberRepository()를 스프링 빈에 등록하고, 스프링 빈에 등록되어 있는 memberRepository()를 memberService()의 인자로 넣어준다.
그러면 아래와 같은 그림처럼 등록된다.
3. DI(의존성 주입)에는 필드주입, setter 주입, 생성자 주입 3가지 방법이 있다.
필드주입
- 필드주입은 추천하지 않는다. spring이 처음 실행할 때만 넣어주고, 중간에 바꿀 방법이 없다.
setter주입
- 누군가가 멤버를 호출했을 때 public으로 열려있어야 하는 단점이 있다.
- 한번 메서드를 작성하고 나면 중간에 바꿀 일이 없는데, 항상 public으로 노출이 된다. (수정될 가능성 있음)
생성자 주입
- 의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다.
* 실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다. 그리고
정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.
* 주의 : @Autowired 를 통한 DI는 helloController, memberService 등과 같이 스프링이 관리하는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.
'BackEnd > Spring' 카테고리의 다른 글
[스프링 입문] 스프링 DB 접근 기술 (0) | 2024.07.02 |
---|---|
[스프링 입문] 회원 관리 예제 - 웹 MVC 개발 (0) | 2024.07.01 |
[스프링 입문] 회원 관리 예제 - 백엔드 개발 (0) | 2024.06.30 |
[스프링 입문] 스프링 웹 개발 기초 (0) | 2024.06.28 |
[스프링 입문] 프로젝트 환경설정 (0) | 2024.06.28 |