Spring/[인프런 김영한 스프링 입문]

[인프런 김영한 스프링 입문] 스프링 빈과 의존관계

h2boom 2024. 8. 9. 16:34

스프링 빈과 의존관계

  • Controller가 Service를 통해 기능을 수행(회원가입, 데이터를 조회....)할 수 있어야 한다.
    => Controller가 Service를 의존한다.
    • Controller와 Service에는 의존관계가 있다. 

 

  • Controller를 작성할 때 클래스 선언부 상단에 @Controller 어노테이션을 작성해줘야한다.
    Service는 @Service, Repository는 @Repository로 명시한다.
    • Controller, Service, Repository를 어노테이션으로 명시해줌으로 스프링에서 관리해야 할 클래스임을 스프링에게 알려주는 역할이다.
  • 스프링이 실행되면 스프링 컨테이너가 생긴다.
    • @Controller, @Service, @Repository 어노테이션을 선언한 클래스의 객체를 생성해서 컨테이너 안에 넣어두고 관리를 한다.
      => 스프링 컨테이너에서 스프링 빈이 관리된다.

 

@Controller
public class MemberController {
	// 직접 주입하는 방식은 좋지 않다.
	// private final MemberService memberService = new MemberService();
    
	//@AutoWired를 통해 스프링 컨테이너의 MemberService를 찾아서 연결해준다.
	private final MemberService memberService;
    
	@Autowired
	public MemberController(MemberService memberService) {
		this.memberService = memberService;
	}
}
  • 예시와 같이 Controller와 Service의 의존관계를 명시할 때 직접 객체를 생성해서 사용하는 방식은 좋지 않다.
  • @AutoWired 어노테이션을 사용하는 방식으로 의존관계를 명시해야한다.
    1. 스프링 컨테이너가 생성되서 Controller의 객체가 스프링 빈으로 등록되서 관리된다.
    2. Service의 객체도 컨테이너의 스프링 빈으로 등록되서 관리가 된다.
    3. Controller의 MemberService와 컨테이너의 스프링 빈으로 등록된 MemberService 객체를 연결시켜준다.
  • 이 방식의 장점으로는 사용할 때마다 객체를 직접 생성할 필요 없이 컨테이너가 스프링 빈으로 등록된 객체를 필요한 곳에 주입시켜준다는 것이다.

 

@Controller
public class MemberController {
    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
    
    //내용 생략
}

@Service
public class MemberService {
    private final MemberRepository memberRepository;

    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    
    // 내용 생략
}

@Repository
public interface MemberRepository {
	//내용 생략
}
  • Controller, Service, Repository에 애노테이션을 선언함으로 스프링 컨테이너에서 객체가 스프링 빈으로 등록되고 관리할 수 있게 되었다.
  • 서로 간의 의존관계를 @AutoWired 어노테이션이 붙은 생성자를 통해 컨테이너에 등록된 스프링 빈 객체를 주입해준다.
    • @AutoWired를 사용하면 객체 생성 시점에 컨테이너에서 해당 스프링 빈을 찾아서 주입한다.
    • 생성자가 한 개인 경우 @AutoWired를 생략할 수 있다.

 

  • 스프링 빈을 등록하는 방법
    1. 컴포넌트 스캔과 자동 의존관계 설정
      • @Component 와 관련된 어노테이션이 있는 클래스의 객체를 컨테이너에 자동으로 등록해서 관리한다.
      • @Controller, @Service, @Repository ... 등의 내부에는 @Component가 포함하고 있다.
      • 스프링을 실행하는 main()이 속한 패키지의 하위에 있는 파일들 중에 @Component가 포함된 클래스를 찾아서 스프링 빈으로 등록한다.
        • main()이 속한 패키지보다 상위 패키지 클래스에 @Component를 선언해도 스프링 빈으로 등록되지 않는다.
    2. 자바 코드로 직접 스프링 빈 등록하기
      • @Configuration 어노테이션을 선언한 클래스에 스프링 빈을 직접 등록하는 방식이다.
      • 각 객체를 리턴해주는 메소드를 만들고 @Bean으로 선언해준다.
      • 이전에는 XML로 작성하는 경우도 있었지만 현재는 Java 코드로 작성한다.
  • 정형화된 Controller, Service, Repository는 컴포넌트 스캔을 사용하고 정형화되지 않거나 상황에 따라 구현체를 변경해야하는 경우에는 설정을 통해 직접 스프링 빈으로 등록한다.
// 직접 스프링 빈을 등록하는 방식
@Configuration
public class SpringConfig {
    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}
  • 스프링에서 스프링 컨테이너에 @Configuration으로 스프링 빈을 등록할 때 기본으로 싱글톤 패턴으로 등록한다.
    • 유일하게 하나만 등록해서 공유하기에 같은 스프링 빈이면 모두 같은 인스턴스이다.
    • @Component는 싱글톤이 보장되지 않는다.

 

@Controller
public class MemberController {
    // 필드 주입
    @Autowired
    private MemberService memberService;


    // 생성자 주입
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }

    // setter 주입
    @Autowired
    public void setMemberService(MemberService memberService) {
        this.memberService = memberService;
    }
}
  • DI(의존관계 주입) 방식
    1. 필드 주입
      • 필드 자체에 @AutoWired로 선언하는 방식
      • 스프링 시작될 때 주입한 이후로 의존관계를 바꿀 수 있는 방법이 없기 때문에 좋지 않은 방식이다.
    2. Setter 주입
      • Setter 메소드에 @AutoWired로 선언하는 방식
      • Setter 메소드를 public으로 노출시킴으로 언제 어디서든 변경이 가능하기에 위험성이 크다.
    3. 생성자 주입
      • 생성자에 @AutoWired로 선언하는 방식
      • 의존관계가 실행중에 동적으로(런타임에) 변하는 경우가 없기 때문에 생성자 주입 방식이 좋다.
  • @AutoWired를 통한 DI는 스프링이 관리하는 객체에서만 동작한다. 
    • 스프링 빈으로 등록되지 않은 객체에서는 @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

 

[지금 무료] 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의 | 김영한 - 인프

김영한 | 스프링 입문자가 예제를 만들어가면서 스프링 웹 애플리케이션 개발 전반을 빠르게 학습할 수 있습니다., 스프링 학습 첫 길잡이! 개발 공부의 길을 잃지 않도록 도와드립니다. 📣 확

www.inflearn.com