데굴데굴 굴러가는 개발 블로그

[ Spring ] DI 의존성 주입 / @RequiredArgsConstructor 본문

개발/Spring

[ Spring ] DI 의존성 주입 / @RequiredArgsConstructor

Daram-e 2022. 11. 1. 09:48
  • 스프링에서 DI(의존성 주입) 시 총 3가지 방법으로 의존성을 주입할 수 있다.
  1. Field(필드) 주입
  2. Setter(수정자) 주입
  3. Constructor(생성자) 주입

Field 주입

  • 멤버 객체에 @Autowired로 의존성을 주입
@Service
public class Example{
		@Autowired
		private ExampleService exampleService;

		@Autowired
		private ExampleRepository exampleRepository;
}

Setter 주입

  • setter 함수에 @Autowired로 의존성 주입
@Service
public class Example{
		private ExampleService exampleService;
		private ExampleRepository exampleRepository;

		@Autowired
		public void setExmapleService(ExampleServicce exampleService){
				this.exampleService = exampleService;
		}

		@Autowired
		public void setExampleRepository(ExampleRepository exampleRepository){
				this.exampleRepository = exampleRepository;
		}
}

Constructor 주입

  • 생성자에 @Autowired로 의존성 주입
@Service
public class Example{
		private ExampleService exampleService;
		private ExampleRepository exampleRepository;

		@Autowired
		public void setExample(ExampleService exampleService, ExampleRepository exampleRepository){
				this.exampleService = exampleService;
				this.exampleRepository = exampleRepository;
		}
}

 

생성자 주입을 권장할까?

  • final 을 사용해 불변 객체를 만들 수 있다.
    • Bean의 생성 시점에 모든 의존 관계를 BeanFactory부터 가져와서 의존성 주입 DI를 진행한다.
    • → @Autowired를 사용하는 두 방법(Field, Setter 주입)은 Null → BeanFactory로부터 Bean이 생성된 후에 instance 돼야 하므로 불변 객체일 수 없다
  • 순환 참조를 막을 수 있다.
    • Bean의 생성 시점에 순환참조로 인한 에러가 발생하므로 사전 체크가 가능하다.
  • NullPointerException, NPE를 막을 수 있다.
    • 객체 생성과 동시에 의존성을 주입해야 하므로 BeanFactory에 해당 Bean이 있는지 검사를 해야 한다.
    • 따라서 NPE 가 발생한다면 의존성을 주입받는 Service 자체가 생성되지 않기 때문에, 런타임 오류가 난다.

- 하지만 생성자 주입은 너무 번거로운 단점이 있다. 필드를 추가하면 생성자를 수정해야 하기 때문이다.  이러한 번거로움을 해결하기 위해 Lombok 이 제공하는 어노테이션이 있다.

@RequiredArgsConstructor

  • final / @NotNull 이 붙은 필드의 생성자를 자동으로 생성해준다.

→ 새로운 필드를 추가할 때 생성자를 다시 만들어야 하는 번거로움을 없앨 수 있다.

→ 하지만 자동적으로 생성자가 만들어지기 때문에 예상하지 못한 결과나 오류가 발생할 수 있다. 동작 원리에 대한 이해가 필요하다.

@Service
@RequiredArgsConstructor
public class Example{
		private final ExampleService exampleService;
		private final ExampleRepository exampleRepository;
}