Spring에서 DI 하는 세가지 방법

Minky·2021년 10월 4일
0

spring에서 의존성 주입하는 세가지 방법에 대해 정리하려 한다.

목차

  • DI(Dependency Injection)란?
  • 필드 주입(Field Injection)
  • 생성자 주입(Constructor Injection)
  • 수정자 주입(Setter Injection)
  • 차이점?


DI(Dependency Injection)란?

스프링 환경에서 개발한다하면 필수적으로 알아야할 특징인 Ioc, DI, AOP, POJO...등이 있는데, 너무나도 잘 정리되있는 글들이 많기 때문에 설명은 생략하겠다.

그중에서 DI(Dependency Injection) 의존성주입 이란 IoC 패턴의 구현방법중 하나이다.

즉, 필요한 객체는 자기가 직접 생성하는 것이 아니라 이미 생성된 객체(빈)을 주입받아 사용하는것!

IoC(Inversion of Control)?
객체의 생성과 관리를 개발자가 아닌 프레임워크, ioc컨테이너가 직접 관리하는것.

필드 주입(Field Injection)

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;
    
}

@Autowired로 주입을 받는 방법.
사용하고자 하는 클래스에 주입받고자 하는 bean을 필드로 선언한 뒤 @Autowired 키워드를 붙여주면 자동으로 주입된다.

수정자 주입(Setter Injection)

스프링 3.x 에서 권고하던 방식. set method를 정의해서 주입받는 방식이다.

@Service
public class UserService {
    private UserRepository userRepository;
 
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

생성자 주입(Constructor Injection)

@Service
public class UserService {

    private UserRepository userRepository;
    
	// 주입받을 객체가 하나면 @Autowired 생략 가능.
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

스프링에서 가장 권고하는 방식. (이유는 아래에 설명)
생성자를 통해서 주입받는 방식인데, 생성자를 만들어야하는 귀찮음(?)이 단점이다.
하지만 이부분도 @RequiredArgsConstructor 이용하여 아래처럼 간결한 코드를 작성할 수있다.

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;
}

@RequiredArgsConstructor
final 이나 @NotNull이 붙은 필드의 생성자를 자동으로 생성해주는 어노테이션.

차이점은?

이 세가지 모두 빈을 주입받는 방법이지만, 차이가 있다.

필드 주입이나 수정자 주입은 런타임 시에 의존성을 주입하기때문에 의존성을 주입하지 않아도 객체가 생성된다.
하지만, 생성자 주입은 객체가 생성되는 시점에 빈을 주입하여, 런타임 전에 의존성이 주입되지 않아 발생할 수 있는 NPE를 방지 할 수 있다.

이 이유때문에 스프링에서는 현재 생성자 주입을 권고하고있고, 그 외에 다음과 같은 장점이 있다.

  • 위의 차이점대로, 필수적으로 사용해야하는 의존성 없이는 객체를 만들지 못하도록 강제할 수 있다.
  • final을 사용할 수있다. (immutable)
  • 컴파일 단계에서 순환 참조를 잡아내어, 미리 방지 할 수 있다.
    => 필드주입이나 수정자주입으로는 순환참조가 가능하지만, 순환참조는 바람직하지 않으므로 최대한 그렇게 설계되지 않도록 하는것이 더 중요하다!
  • DI프레임워크에 의존하지 않고 순수한 자바의 특징을 잘 살리는 방법이다.
  • 테스트코드 작성시 의존성 주입이 편하다. (@Autowired같은 경우는 @SpringBootTest가 필요)

참고

https://devlog-wjdrbs96.tistory.com/165
https://velog.io/@gillog/Spring-DIDependency-Injection-%EC%84%B8-%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95
https://baek.dev/post/21/

profile
소통하는 Web Developer가 되고 싶습니다 :)

0개의 댓글