Spring - Autowired


Autowired

  • Autowired 는 스프링에서 자동으로 의존관계를 주입시켜주는 어노테이션이다.
  • 스프링 컨테이너에 등록되어있어야 한다.



의존성 주입이란?

  • Spring Framework의 3가지 핵심 프로그래밍 중 하나로 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴

  • 인터페이스를 사이에 둬서 클래스 레벨에서는 의존관계가 고정되지 않도록 하고

  • 런타임시에 관계를 동적으로 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해준다



주입 방식

  • 수정자, 생성자, 필드주입, 일반메서드 주입 방식이 있다.
  • 원래는 필드주입 방식을 사용했는데 스프링환경을 무조건 실행해야지만 테스트할 수 있고, 순수 자바 환경에서는 구현체를 바꾸거나 new 할 수가 없어서 테스트가 어려웠다.
  • 그래서 수정자 방식을 선택하였음.
  • 근데 외부에서 수정할 수 있는 로직을 넣는다는게 마음에 안들고, 문제가 생길 수도 있어서 생성자 방식으로 바꾸게 되었다.
  • 일반메서드 주입 방식은 아무 메서드에다가 생성자처럼 넣는건데 수정자 주입이랑 비슷한 메커니즘이고 잘 사용하지 않는다.


필드주입

  • 필드에 바로 의존 관계 주입

  • 외부에서 접근이 불가능하다는 단점

  • 필드 주입을 사용하면 의존성 주입을 위해 Spring Container가 필요하게 되므로 테스트가 어렵다.

  • 실제 코드와 무관한 테스트 코드나 설정을 위해 불가피 한 경우에만 사용

  • 참고로, Java의 Reflection API를 사용하면 접근 제한자를 무시하고 필드에 직접 접근할 수 있다. ( 그래서 private 인데, 필드 주입이 가능한 것이다. )

  • Spring Framework는 이러한 Reflection API를 사용해 private으로 선언된 필드에도 의존성을 주입할 수 있다.

@Autowired
private TestService testService;


수정자 주입

  • 필드 값을 변경하는 Setter를 통해서 의존 관계 주입

  • 주입받는 객체가 변경될 가능성이 있는 경우

  • 이 방법은 객체가 생성된 후에도 의존성을 변경할 수 있다는 점에서 유연성을 제공하지만, 의존성이 변경될 가능성이 있기 때문에 불변성을 확보하기 어렵다.

private TestService testService;

@Autowired
public void setEngine(TestService testService) {
	this.testService = testService;
}


생성자 주입

  • 생성자의 호출 시점에 1회 호출 되는 것이 보장

  • 주입받은 객체가 변하지 않거나, 반드시 객체의 주입이 필요한 경우에 강제하기 위해 사용

private final TestService testService;

@Autowired
public TestClass(TestService testService) {
	this.testService = testService;
}



생성자 주입을 사용해야 하는 이유

  • 객체의 불변성

    • 의존 관계의 변경이 필요한 상황은 거의 없기 때문에

    • 수정자 주입이나 일반 메서드 주입 등을 이용하면 불필요하게 수정의 가능성을 열어두기 때문에 유지보수성을 떨어뜨린다.

    • 즉, 수정자 주입을 사용하면 객체의 불변성을 떨어뜨린다고 볼 수 있고, 유지보수성이 떨어진다.

  • 테스트 코드의 작성

    • 생성자 주입이 아닌 다른 주입으로 작성된 코드는 순수한 자바 코드로 단위 테스트를 작성하기 어려움

    • 생성자 주입 사용시 컴파일 시점에 객체를 주입받아 테스트 코드를 작성, 주입하는 객체의 누락시 컴파일 시점에 오류 발견 가능

    • 특히, 필드 주입을 사용하면 의존성 주입을 위해 Spring Container가 필요하게 되므로 테스트가 어렵다.

    • 그리고 필드 주입을 사용하면 객체가 생성된 후에도 의존성이 변경될 수 있다. 이는 불변성을 해칠 수 있으므로 객체의 안정성을 보장하기 어렵다.

    • 생성자 주입을 사용하면, 객체가 생성될 때 의존성을 한번에 주입받아 불변성을 확보할 수 있다.

    • 즉, 필드 주입방식을 사용하면, 스프링 컨테이너가 필수적이므로 테스트가 어렵고, 불변성을 해칠 수 있기 때문에 사용하지 않는다.

  • final 키워드와 Lombok과의 결합

    • 생성자 주입 사용시 필드 객체에 final 키워드를 사용할 수 있기 때문에 컴파일 시점에 누락된 의존성을 확인할 수 있다.

    • final 키워드 작성시 Lombok과 결합하여 간결한 코드를 작성할 수 있다.



결론

  • 테스트시에는 필드 주입
  • 실제로 작성하는 코드는 생성자 주입 방식을 사용하는 것이 좋다.
  • 또한 요즘은 lombok을 활용하여 @RequiredArgsConstructor 라는 특정 필드를 매개변수로 받는 생성자를 자동으로 생성해주는 어노테이션을 활용한다.
    • 단, 필드가 final로 되어있어야 함.






results matching ""

    No results matching ""