DI(Dependency Injection)는 의존성 주입으로, 하나의 객체가 다른 객체의 의존성을 제공하는 기술입니다.
클래스 레벨에서는 의존관계가 고정되지 않고 런타임 시에 관계를 동적으로 주입해주어서,
유연성을 확보하고 결합도를 낮출 수 있게 해줍니다.
Spring에서 의존성을 주입하는 방법에는 3가지가 있습니다.
결론부터 말하면 생성자 주입 방법을 사용하는 것이 좋습니다.
java
1 @Controller 2 public class ExampleController { 3 private final ExampleService1 service1; 4 private final ExampleService2 service2; 5 6 // Class내 생성자가 하나뿐이면 @Autowired 생략 가능 7 @Autowired 8 public ExampleController(ExampleService1 service1, ExampleService2 service2) { 9 this.service1 = service1; 10 this.service2 = service2; 11 } 12 }
생성자 주입은 생성자 호출 시점에 1회 호출 되는 것이 보장되어서, 주입받은 객체가 변하지 않게 됩니다.
java
1 @Controller 2 public class ExampleController { 3 @Autowired 4 private final ExampleService1 service1; 5 @Autowired 6 private final ExampleService2 service2; 7 }
필드 주입은 코드가 간결해지고 유지보수가 편해지는 장점이 있습니다.
하지만 외부에서 접근이 불가능하다는 단점이 있습니다.
또한 반드시 Spring과 같은 DI 프레임워크가 존재해야 하기 때문에 사용을 지양합니다.
java
1 @Controller 2 public class ExampleController { 3 private final ExampleService1 service1; 4 private final ExampleService2 service2; 5 6 @Autowired 7 public void setService1(ExampleService1 service1) { 8 this.service1 = service1; 9 } 10 11 @Autowired(required = false) 12 public void setService2(ExampleService2 service2) { 13 this.service2 = service2; 14 } 15 }
Setter 주입은 생성자 주입과 다르게 주입받는 객체가 변경될 가능성이 있는 경우에 사용합니다.
@Autowired 어노테이션은 주입할 대상이 없는 경우에는 오류가 발생합니다.
따라서 주입할 대상이 없어도 동작하도록 하려면 requried = false를 이용해 설정할 수 있습니다.
생성자 주입은 필드 객체에 final 키워드를 사용할 수 있습니다.
Lombok의 @RequiredArgsConstructor를 활용하면,
final 변수를 위한 생성자를 대신 생성해줍니다.
이를 활용하면 새로운 객체를 추가하거나 기존 객체를 삭제할 때 등등…
유지보수가 간결해지며 코드 작성시에도 간편해집니다.
java
1 // 변경 전 2 @Controller 3 public class ExampleController { 4 private final ExampleService1 service1; 5 private final ExampleService2 service2; 6 7 public ExampleController(ExampleService1 service1, ExampleService2 service2) { 8 this.service1 = service1; 9 this.service2 = service2; 10 } 11 } 12 13 // 변경 후 14 @RequiredArgsConstructor 15 @Controller 16 public class ExampleController { 17 private final ExampleService1 service1; 18 private final ExampleService2 service2; 19 }
변경 전과 변경 후의 코드가 동일한 생성자 주입을 하는 코드가 됩니다.
코드 작성이 편해지면서 수정이 적어집니다.