스프링 빈을 등록하는 방법은 2가지가 있다.
- 1. 컴포넌트 스캔과 자동 의존관계 설정
- 2. 자바 코드로 직접 스프링 빈 등록하기
1. 컴포넌트 스캔과 자동 의존관계 설정
흔히 우리가 자주보는 어노테이션 방식이 1번 방식에 속한다.
1) @Autowired
helloController 객체를 생성할 때 memberService를 넣어주기 위해 @Autowired를 이용한다고 가정하자. 아래는 생성자 주입의 예시이다.
@Controlloer
public class HelloController{
private final MemberService memberService;
@Autowired
public HelloController(MemberService memberservice){
this.memberservice = memberservice;
}
}
스프링 컨테이너를 구동시키면 helloController가 실행이 될 때 스프링 빈에 등록되어 있는 memeberService 객체를 가져다가 자동으로 넣어준다. 이게 바로 DI(Dependency Injection)이라고 한다. 의존관계를 주입해주는 것이다.
2) @Controller / @Service / @Repository
만약 위 코드에서 MemberService memberservice 즉, 파라미터 부분에 빨간줄이 떴다면 스프링 컨테이너가 등록된 @Service 스프링빈을 못찾는 것이다. 즉, MemberService 자바 class에 @Service 표시를 하지 않아 스프링빈으로 등록되지 않은 것이다.
이는 @Repository도 마찬가지이다. @Service는 내부 로직을 담당하는 만큼 저장소를 왔다갔다하는데 이 때 Repository가 꼭 필요하다. 때문에 MemberRepository에도 @Repository 표시를 꼭 해야 스프링 컨테이너가 찾을 수 있다.
또한 이 3가지 어노테이션은 @Component를 포함하고 있다.
스프링이 올라오면 com.~~ 패키지에 있는 ~~Application의 main 메소드부터 시작한다. @SpringBootApplication이 붙어있다.
@SpringBootApplication가 붙어있는 패키지와 같은 (하위)패키지들은 컴포넌트 스캔을 진행하게 된다.
@Component 붙은 class의 객체를 모두 생성해 스프링 컨테이너에 등록한다. 이 때 @Autowired가 객체 간의 연관관계를 설정하는 것이다.
1-1. 싱글톤 패턴
스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다. 이 때 싱글톤은 유일하게 하나의 객체만 등록해서 관리하는 것이다. 만약 MemberService나 PayService가 있다고 가정하면 회원 정보에 접근하기 위해 MemberRepository가 필요해 요청할 것이다. 이 때 MemberService와 PayService는 동일한 MemberRepository를 보게되는 것이다.
따라서 같은 스프링 빈이면 모두 같은 인스턴스이다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.
2. 자바 코드로 직접 스프링 빈 등록하기
어노테이션 방식을 사용하지 않고, SpringConfig class를 만들어 스프링빈을 등록하는 방법이다.
//SpringConfig class 파일
@Configuration
public class SpringConfig{
@Bean
public MemberService memberService(){
return new MemberService(memberRepository()); //의존관계 주입
}
@Bean
public MemberRepository memberRepository(){//MemberRepository는 인터페이스
return new MemoryMemberRepository(); //MemoryMemberRepository는 구현체
}
}
@Controller는 써야한다. 어차피 스프링 컨테이너가 관리하는 것이기 때문이다. Controller 생성자에 @Autowired를 붙여주면 SpringConfig에 @Bean으로 등록된 요소들 중 필요한 것을 넣어주게 된다.
과거에는 xml(html처럼 태그를 이용하는 방식)을 이용해서 설정했지만 요즘에는 거의 자바코드로 많이 설정한다.
이 방식의 장점은 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야 하면 위처럼 설정하는 방식이 좋다.
예를 들어 DB 저장소를 교체하고 싶을 때 MemoryMemberRepository() -> DBRepository() 이런식으로만 바꾸면 다른 코드 손 댈 필요 하나 없이 설정파일 수정으로 간편하게 바꿀 수 있다. 그래서 interface도 만들어주는 것이다.
3. DI의 3가지 방식
1. 생성자 주입 (추천)
@Controlloer
public class HelloController{
private final MemberService memberService;
@Autowired
public HelloController(MemberService memberservice){
this.memberservice = memberservice;
}
}
스프링 컨테이너로 조립하는 시점에 생성자로 memberService가 1번 들어오고 끝나니까 가장 최선의 방법이다.
2. 필드 주입
@Controlloer
public class HelloController{
@Autowired private final MemberService memberService;
}
중간에 주입값을 바꿀 수 있는 방법이 없다. 별로 안좋은 방법이다.
3. setter 주입
@Controlloer
public class HelloController{
private MemberService memberService; //final 제거
@Autowired
public void setMemberService(MemberService memberservice){
this.memberservice = memberservice;
}
}
누군가가 MemberController를 요청할 때 setMemberService가 public으로 열려있어야 한다.
setMemberService를 단 1번 셋팅하고 나면 중간에 바꿀 일이 없어야 하는데 만약 중간에 바꾸면 잘못 될 가능성이 농후하다.
'BE > Spring' 카테고리의 다른 글
데이터베이스 스프링에 연결하기 (1. 순수 JDBC 방식), DI와 OCP (0) | 2024.01.05 |
---|---|
h2 실습용 데이터베이스 실행 방법 (0) | 2024.01.05 |
스프링 웹 개발 종류 (0) | 2024.01.03 |
cmd로 Spring 실행시키는 법 (빌드란?) (0) | 2024.01.03 |
인텔리제이 gladle 설정 다시하기 : Could not resolve all files for configuration ':classpath'. > Could not resolve org.springframework.boot:spring-boot-gradle-plugin:3.0.10. (0) | 2023.09.13 |