본문 바로가기
Java | Spring/Spring 입문

[스프링 입문] 4.1 스프링 빈과 의존관계

by 동기 2022. 3. 12.
반응형

순서


4.1 컴포넌트 스캔과 자동 의존관계 설정

 

스프링 빈을 등록하고, 의존관계 설정하기

멤버 컨트롤러가 회원서비스와 리포지토리를 사용할 수 있게 의존관계를 준비하자.

 

멤버 컨트롤러에 의존관계 추가

먼저 컨트롤러를 생성 해 보자

@Controller
public class MemberController {
	
    
}

MemberController 위에 @Controller 어노테이션을 작성하면, 스프링은 이 어노테이션을 보고 멤버컨트롤러 객체(스프링 빈)를 생성해서 스프링 컨테이너에 넣고, 스프링이 관리한다. 

 

 

MemberController에 MemberService추가

@Controller
public class MemberController {
	private final MemberService memberService = new MemberService();    
}

이전에는 new 연산자를 이용해 MemberService를 새로 생성했었다. 이는 다른 컨트롤러들도 new로 생성하여 memberService를 가져다 쓸 수 있기 때문에, 많은 문제가 발생한다.

memberService는 기능이 많이 없어서, 스프링 빈으로 하나만 등록하고 공용으로 쓰는것이 낫다. ( 스프링 컨테이너에는 하나만 등록이 되기 때문 + @부가적인 효과 )

또한 우리는 스프링 프레임웤을 이용하기 때문에 스프링이 관리하고 스프링 컨테이너에서 받아서 쓰는것이 바람직 하기 때문이다.

 

위의 MemberController를 아래와 같이 변경해 보자

@Controller
public class MemberController {
	//private final MemberService memberService = new MemberService();
    
    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
    
}

우리는 @Controller 어노테이션을 작성을 하면, 스프링 컨테이너가 뜰 때 MemberController를 스프링 빈으로 생성하는 것을 알고 있다.

 

MemberController를 생성하는 과정에서 MemberService객체를 새로 생성하는 것이 아닌, MemberController의 생성자 호출 시 매개 변수로 memberService를 받아서 생성 하도록 변경을 하였다.

 

여기에 생성자에 @Autowired 를 추가하면, 생성자의 매개변수인 memberService를 스프링이 스프링 컨테이너에 있는것을 가져와서  넣어준다. ( 즉 생성 시점에 컨테이너에서 해당 빈을 찾아서 주입한다.) 생성자가 1개만 있으면 @Autowired는 생략할 수 있다.

스프링 컨테이너에 있는 스프링빈을 가져오기 위해 @Autowired 추가

다만 지금은 빨간줄이 있어 빌드시 오류가 뜰 것이다. 

MemberController의 생성자의 빨간밑줄에 마우스를 올려보면, MemberService 빈을 찾을 수 없어 autowire를 할 수 없다고 뜬다.

 

이유는 MemberService는 현재 어떠한 어노테이션이 없는 순수한 자바 클래스 이기때문에, 스프링은 이 놈이 스프링 빈인지 모른다.

순수 MemberService java Class

 

 

 

따라서 이 MemberService를 빈으로 등록해주면 된다.

방법은 MemberService 클래스에 @Service를 작성하면 끝이다.(매우 간단! 스프링이 @Service 어노테이션을 보고 컨테이너에 등록을 해 주어서, MemberController의 생성자에서 쓸 수 있게 된다.)

MemberService 클래스 위에 @Service 어노테이션 추가

 

생성자 매개변수 memberService에 빨간 밑줄이 없어진 모습

 

(마찬가지로 MemberService의 생성자도 memberRepository를 매개변수로 받기 때문에, 구현체인 MemoryMemberRepository클래스에 @Repository 를 추가하여 스프링 빈으로 등록하면, MemberService가 생성될때 스프링 컨테이너에 등록된MemoryMemberRepository 스프링 빈을 가져와 쓴다. 이것이 바로 Dependency Injection - 의존관계를 외부에서 주입 )

  • 주의: @Autowired 를 통한 DI helloConroller , memberService 등과 같이 스프링이 관리하는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

 

이렇게 각자 스프링 컨테이너에 있는것을 필요에 따라 가져다 연결하여 쓰면 된다.

( Controller, Service , Repository - 정형화된 패턴이다 )

 

상기와 같은 방법으로 스프링 빈을 등록하는 방법이 컴포넌트 스캔과 자동 의존관계 설정 방식이다.

(왜 컴포넌트 스캔이냐면, @Service, @Repository 로 작성한 클래스들도 들여다 보면 @Component가 붙어 있다. 컴포넌트와 관련된 어노테이션을 가진 클래스들은 스프링에서 객체를 생성해서 스프링 컨테이너에 등록해준다. 등록된 컴포넌트들을 스캔해서 DI 를 하기 때문.)

참고: 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유한다.메모리 절약하고 좋다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.

 

반응형

댓글