Field Injection이란 정확히 무엇이며 어떻게 피할 수 있습니까? @Autowired

필드 주입 이 권장되지 않는 Spring MVC 및 Portlets에 대한 일부 게시물을 읽었습니다 . 내가 이해하는 것처럼 필드 주입 은 다음과 @Autowired같이 Bean을 주입하는 것입니다.

@Component
public class MyComponent {
    @Autowired
    private Cart cart;
}

내 연구 중에 생성자 주입에 대해서도 읽었습니다 .

@Component
public class MyComponent {
    private final Cart cart;

    @Autowired
    public MyComponent(Cart cart){
       this.cart = cart;
    }
}

이 두 가지 유형의 주사의 장점과 단점은 무엇입니까?


편집 1 : 이 질문의 중복으로 표시되기 때문에 이 질문에 내가 그것을 확인. 질문이나 답변에 코드 예제가 없기 때문에 어떤 주입 유형을 사용하고 있는지 내 추측에 맞다면 명확하지 않습니다.



답변

주입 유형

종속성을 Bean에 삽입하는 방법에는 세 가지 옵션이 있습니다.

  1. 생성자를 통해
  2. setter 또는 기타 방법을 통해
  3. 반사를 통해 직접 필드로

당신은 옵션 3을 사용하고 있습니다. 그것은 당신이 @Autowired당신의 분야에서 직접 사용할 때 일어나는 일 입니다.


주입 지침

Spring에서 권장 하는 일반 지침 ( Constructor 기반 DI 또는 Setter 기반 DI 섹션 참조 )은 다음과 같습니다.

  • 필수 종속성 또는 불변성을 목표로하는 경우 생성자 주입을 사용하십시오.
  • 선택적 또는 변경 가능한 종속성의 경우 setter 주입을 사용하십시오.
  • 대부분의 경우 필드 주입을 피하십시오

현장 주입 단점

필드 주입이 눈살을 찌푸리는 이유는 다음과 같습니다.

  • 생성자 주입으로 할 수있는 것처럼 불변 객체를 만들 수 없습니다.
  • 클래스는 DI 컨테이너와 긴밀하게 연결되어 있으며 외부에서 사용할 수 없습니다.
  • 리플렉션 없이는 클래스를 인스턴스화 할 수 없습니다 (예 : 단위 테스트). 인스턴스화하려면 DI 컨테이너가 필요하므로 테스트가 통합 테스트와 비슷해집니다.
  • 실제 종속성은 외부에서 숨겨지며 인터페이스 (생성자 또는 메서드)에 반영되지 않습니다.
  • 10 개 정도의 의존성을 갖는 것은 정말 쉽습니다. 생성자 주입을 사용하는 경우 10 개의 인수가 포함 된 생성자가있을 것입니다. 그러나 필드 주입을 사용하여 주입 된 필드를 무기한 추가 할 수 있습니다. 종속성이 너무 많으면 클래스가 일반적으로 하나 이상의 작업을 수행하고 단일 책임 원칙을 위반할 수 있다는 위험 신호입니다.

결론

필요에 따라 주로 생성자 주입을 사용하거나 생성자와 세터 주입을 혼합하여 사용해야합니다. 현장 주입에는 많은 단점이 있으므로 피해야합니다. 필드 주입의 유일한 장점은 모든 단점을 능가하지 않는 쓰기가 더 편리하다는 것입니다.


추가 읽기

필드 주입이 일반적으로 권장되지 않는 이유에 대한 블로그 기사를 작성했습니다. 필드 종속성 주입은 유해한 것으로 간주 됩니다.


답변

이것은 소프트웨어 개발에서 끝없는 논의 중 하나이지만 업계의 주요 영향력있는 사람들은이 주제에 대해 더 많은 의견을 얻고 있으며 더 나은 옵션으로 생성자 주입을 제안하기 시작했습니다.

생성자 주입

장점 :

  • 더 나은 테스트 가능성 . 단위 테스트에서 모의 ​​라이브러리 나 Spring 컨텍스트가 필요하지 않습니다. 키워드 로 테스트 할 개체를 만들 수 있습니다 . 이러한 테스트는 반사 메커니즘에 의존하지 않기 때문에 항상 더 빠릅니다. ( 이 질문 은 30 분 후에 질문 되었습니다. 작성자가 생성자 주입을 사용했다면 나타나지 않았을 것입니다.)
  • 불변성 . 종속성이 설정되면 변경할 수 없습니다.
  • 더 안전한 코드 . 생성자를 실행하면 매개 변수로 전달 된 모든 것을 검증 할 수 있으므로 객체를 사용할 준비가됩니다. 객체는 준비 상태 일 수도 있고 아닐 수도 있으며 중간에 상태가 없습니다. 필드 주입을 사용하면 물체가 깨지기 쉬운 경우 중간 단계를 도입 할 수 있습니다.
  • 필수 종속성의 깔끔한 표현 . 이 문제에서 현장 주입은 모호합니다.
  • 개발자가 디자인에 대해 생각하게합니다 . dit는 8 개의 매개 변수를 가진 생성자에 대해 썼는데, 이것은 실제로 나쁜 디자인의 신호이며 God object anti-pattern 입니다. 클래스의 생성자 또는 필드에 8 개의 종속성이 있는지 여부는 중요하지 않으며 항상 잘못되었습니다. 사람들은 필드를 통하는 것보다 생성자에 더 많은 종속성을 추가하는 것을 더 꺼립니다. 잠시 멈추고 코드 구조에 대해 생각해야한다는 신호로 뇌에 신호를 보냅니다.

단점 :

  • 더 많은 코드 (그러나 최신 IDE는 고통을 덜어줍니다).

기본적으로 필드 주입은 그 반대입니다.


답변

맛의 문제. 당신의 결정입니다.

하지만 왜 생성자 주입을 사용하지 않는지 설명 할 수 있습니다 .

  1. 모든 @Service, @Repository@Controller콩에 대한 생성자를 구현하고 싶지 않습니다 . 약 40-50 개 이상의 콩이 있습니다. 새 필드를 추가 할 때마다 생성자를 확장해야합니다. 아뇨. 원치 않으며 그럴 필요도 없습니다.

  2. Bean (서비스 또는 컨트롤러)에 많은 다른 Bean을 주입해야하는 경우 어떻게됩니까? 4 개 이상의 매개 변수가있는 생성자는 매우 추합니다.

  3. CDI를 사용하는 경우 생성자가 신경 쓰지 않습니다.


편집 # 1 : Vojtech Ruzicka는 다음과 같이 말했습니다.

클래스에 너무 많은 종속성이 있으며 아마도 단일 책임 원칙을 위반하고 리팩토링되어야합니다.

예. 이론과 현실. 여기에 en 예제가 있습니다 : DashboardControllermapping to single path *:8080/dashboard.

My DashboardController는 다른 서비스에서 많은 정보를 수집하여 대시 보드 / 시스템 개요 페이지에 표시합니다. 이 단일 컨트롤러가 필요합니다. 따라서이 경로 (기본 인증 또는 사용자 역할 필터) 만 보호해야합니다.

편집 # 2 : 모든 사람이 생성자의 8 개 매개 변수에 초점을 맞추고 있기 때문에 … 이것은 고객의 레거시 코드 인 실제 사례였습니다. 나는 그것을 변경했습니다. 4 개 이상의 매개 변수에 대해 동일한 주장이 나에게 적용됩니다.

인스턴스 생성이 아니라 코드 주입에 관한 것입니다.


답변

한 가지 더 의견-Vojtech Ruzicka는 Spring이 다음 세 가지 방법으로 빈을 주입한다고 말했습니다 (가장 많은 포인트를 가진 답변).

  1. 생성자를 통해
  2. setter 또는 기타 방법을 통해
  3. 반사를 통해 직접 필드로

이 대답은 잘못되었습니다-모든 종류의 주입 스프링은 반사를 사용하기 때문입니다! IDE를 사용하고 setter / 생성자에 중단 점을 설정하고 확인합니다.

이것은 맛의 문제 일 수 있지만 CASE의 문제 일 수도 있습니다. @dieter는 현장 주입이 더 좋은 경우 훌륭한 사례를 제공했습니다. Spring 컨텍스트를 설정하는 통합 테스트에서 필드 주입을 사용하는 경우-클래스의 테스트 가능성을 가진 인수도 유효하지 않습니다-나중에 테스트에서 통합 테스트에 작성하고 싶지 않은 경우;)


답변