15. 자바 코드로 직접 스프링 빈 등록하기

이번에는 @Autowired말고 하나하나 직접 스프링 빈에 등록해보자. HelloController를 제외하고 MemberService, MemberRepository의 @Service, @Repository, @Autowired를 모두 지운다.

이 상태로 실행하면 당연히 스프링이 올라올때 컴포넌트 스캔이 안되서 스프링빈에 등록되지 않는다.

따라서 hellospring 패키지에 SpringConfig 클래스를 하나만들고 @Configuration 애노테이션을 붙인다. 그 다음 memberService와 memberRepository 메서드를 만들고 @Bean 애노테이션으로 스프링 빈 등록한다. 이때 MemberService 생성자로 MemberRepository 파라미터가 필요하므로 밑에 선언한 MemberRepository 메서드가 반환하는 MemoryMemberRepository 인스턴스를 생성자에 주입시켜준다.

근데 컨트롤러는 어쩔 수없다. 컨트롤러는 스프링이 어쨋든 관리하는거기 때문에 @Controller 는 그대로두면 얘는 컴포넌트 스캔으로 스프링 빈에 등록이 되고 컴포넌트 스캔으로 인해 @Autowired로 멤버서비스와 연결한다.

그러면 방금 등록한 이 memberService()를 딱 넣어준다.

정상적으로 실행이 잘 된다.

이렇게만 하면

딱 이 그림이 완성된거다.


뭐가 더 편할까? 당연히 컴포넌트 스캔하는게 그냥 애노테이션만 달아주면 되니까 편하다.

근데 각자의 장단점이 있음. (나중에 설명)

참고 : 옛날에는 이 설정을 XML로 설정하기도 했음. 최근에는 잘 사용안함

우리가 앞에서 컴포넌트 스캔할때 @Autowired를 이용하여 생성자를 통해 인스턴스를 주입했는데,

Dependency Injection에는 3가지 방법이잇다.

1. 생성자 주입 (우리가 한거)

2. 필드 주입

그러나

인텔리제이는 필드 주입을 추천하지 않음. 실제로 필드 주입은 별로 안좋다. 왜냐면 필드 주입은 바꿀 수 있는 방법이 없다. 스프링 뜰때만 넣어주고 중간에 바꿔서 넣을 수 있는 방법이 없다.

 

3. Setter 주입

멤버 컨트롤러는 생성되는 대로 생성되고, 세터는 호출될때 멤버서비스가 주입이된다. 이거의 단점은 누군가가 멤버컨트롤러를 호출할때 setMemberService가 public으로 열려있어야 한다. 사실 이 setMemberService를 중간에 호출해서 바꿔치기할 일은 거의없다. 한번 세팅되고 나면 중간에 바꿀 일이 없다. 근데 어쨋든 setMemberService가 public에 노출된다. 그래서 잘못 바꾸면 문제가 생긴다.

 

예를들어

멤버 서비스를 세터를 통해 주입시키게 되면

아무 개발자나 다 저렇게 세터를 호출할 수 있게 열려있게 되버린다. 개발은 최대한 호출하지 않아야될 메서드는 호출하면 안된다. 그래서 조립하는 시점에 생성자로 딱 한번만 연결시키고 그다음에 변경을 못시키도록 끝내버리는게 깔끔하고 안전하다. 그래서 요즘 가장 권장하는 스타일이 생성자 주입이다.

 

참고 : 이러한 의존관계가 실행중에 동적으로 변하는 경우는 거의 없다. (실행중에 동적으로 변한다는 의미는 서버가 떠있는 중간에 바꿔치기가 된다는 의미인데, 이런일은 거의 없고 만약 그런일이 일어난다면 Config 파일을 수정하고 서버를 다시 올리면 된다.)

 

* 실무에서는 주로 정형화된 컨트롤러, 서비스 ,리포지토리 컴포넌트 스캔을 사용한다. 근데 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.

우리는 앞서 비즈니스 로직의 db가 아직 정해져있지않아서 메모리를만들고 교체하기로 했었다. 그래서 그림과 같이 메모리멤버리포지토리를 구현체로 만들어 뒀는데, 나중에 이 메모리멤버리포지토리를 다른 리포지토리로 바꿔치기 할거다. 근데 기존에 운영중인 코드를 하나도 안고치고 바꿀 수 있는 방법이 바로 config파일을 따로 관리하는 거다.

다른코드를 전혀 손댈 필요없이 이렇게 config파일에서 Db로만 바꿔주면 된다! 컴포넌트 스캔을 사용하면 여러 코드를 바꿔야하는 상황이 오는데, 직접 설정해주면 그럴 필요가 없다. 참고로 컴포넌트 스캔이나 빈 등록없이 생성자에 @Autowired는 먹지 않는다. 우선 스프링 빈에 등록이 되어야 그다음에 @Autowired로 연결이 되기 때문이다.

 

출처 : 인프런의 김영한 선생님 강의를 정리한 글입니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/dashboard

댓글

Designed by JB FACTORY