인프런 🍀

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

의정부핵꿀밤 2022. 9. 6. 15:18
728x90

  • 스프링에는 위와 같이 클래스 별로 의존 관계가 존재한다

 

 

@Controller
public class MemberController {

 	private final MemberService memberService;
    
 	@Autowired
 	public MemberController(MemberService memberService) {
 		this.memberService = memberService;
 	}
}
  • 위의 코드와 같이 생성자에 @Autowired 가 있으면 Spring이 자동으로 객체 생성 시점에 연관된 객체를 스프링 컨테이너에서 해당 스프링 빈을 찾아서 넣어준다
  • 이렇게 객체 간의 의존 관계를 외부(spring)에서 넣어주는 것을 DI(Dependency Injection), 의존성 주입이라고 한다
  • @Autowired 를 사용하면 개발자가 직접 의존성을 주입할 필요 없이 스프링이 주입해준다
  • 생성자가 1개만 있으면 @Autowired 는 생략이 가능하다

 

  • 그러나 이 때 주입하는 객체가 스프링 빈으로 등록되어 있지 않다면 오류가 발생한다

 

  • 위의 코드에서는 Controller는 @Controller 를 통해서 자동으로 스프링 빈으로 등록되었다
  • 하지만 MemberService는 스프링 빈으로 등록되어 있지 않아서 위와 같은 오류가 발생한 것이다

 

 

스프링 빈을 등록하는 2가지 방법

  1. 컴포넌트 스캔과 자동 의존관계 설정
  2. 자바 코드로 직접 스프링 빈 등록하기

 

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

컴포넌트 스캔 원리

  • @Component 애노테이션이 있으면 스프링 빈으로 자동 등록된다
  • @Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문이다
  • @Component 를 포함하는 아래의 어노테이션도 스프링 빈으로 자동 등록된다
    • @Controller
    • @Service
    • @Repository

 

💡 위의 어노테이션들을 확인해보면 내부에 @Component를 포함하고 있기 때문에 스프링 빈으로 자동 등록이 가능한 것이다

 

💡 참고 : 스프링은 스프링 컨테이너에 스프링 빈을 등록할 떄, 기본으로 싱글톤으로 등록한다. 따라서 같은 스프링 빈이면 모두 같은 인스턴스인 것이다! 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다

 

 

 

 

 

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

실습에서는 MemberService와 MemoryMemberRepository의 @Service, @Repository, @Autowired 어노테이션을 제거하고 진행한다

 

config 파일 위치

위와 같이 SpringConfig 클래스를 생성해서 추가한다

 

 

package hello.hellospring;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.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();
	}
}
  • 그리고 SpringConfig 파일의 코드는 위와 같이 작성한다
  • 이 때 MemberService 생성자에 MemoryMemberRepository를 주입해줘야 하므로 위와 같이 new로 MemberService를 생성할 때 넣어주면 Bean 객체가 주입된다
  • 실무에서는 주로 정형화된 컨트롤러(@Controller), 서비스(@Service), 리포지토리(@Repository) 같은 컴포넌트 스캔을 사용한다
  • 그러나 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야 하면 설정(config 파일)을 통해 스프링 빈으로 등록한다
    • 변경해야 하는 경우 config 파일만 수정하면 되기 때문에 훨씬 편리하다

 

💡 이 때 controller를 어차피 스프링이 관리하기 때문에 @Controller를 이용해서 컴포넌트 스캔 시 올리고, @Autowired로 MemberService를 주입해준다

 

 

의존 관계를 주입하는 여러가지 방법

 

1. XML로 설정

XML 설정을 통해 의존관계를 설정할 수 있지만, 이는 최근에는 잘 사용되지 않는다

 

 

2. 필드 주입

@Autowired private MemberService memberService
  • DI를 위처럼 필드로 주입할 수 있다
  • 이는 중간에 변경할 수 없어서 권장되지 않는다

 

3. setter 주입

@Autowired
public void setMemberService(MemberService memberService) {
	this.memberService = memberService;
}
  • 이를 하기 위해서는 setter가 public으로 선언되어 있어야 하는데, 그럼 외부에서도 누구나 값을 주입할 수 있게 된다
  • 사실상 의존성 주입은 처음에 애플리케이션 조립(컴파일) 시에만 필요하고 이후에는 바뀔 일이 없어서 권장되지 않는다
  • 거의 사용되지 않음!

 

 

4. 생성자 주입

@Controller
public class MemberController {

 	private final MemberService memberService;
    
 	@Autowired
 	public MemberController(MemberService memberService) {
 		this.memberService = memberService;
 	}
}
  • 위처럼 생성자를 통해서 주입하는 방법이다
  • 의존관계가 실행 중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다

 

🚨 @Autowired를 통한 DI
● @Autowired를 통한 DI는 스프링이 관리하는 객체에서만 동작한다
● 만약 스프링 빈으로 등록하지 않고, 내가 직접 new로 생성한 객체에서는 동작하지 않는다
● 따라서 @Autowired를 사용하려면 @Component나 @Bean을 통해 스프링 빈으로 등록해야 한다

 

728x90