프레임워크/Spring

[Spring] Autowired 필드주입은 왜 지양해야 하는가?

멍토 2022. 3. 20.

FieldInject

package com.example.demo.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class FieldInject {

    @Autowired
    private Field1 field1;

    public Field1 getField1() {
        return field1;
    }
}

 

인텔리제이에서 위와같이 필드주입을 하면 아래와 같은 글이 나오게 된다.

Field injection is not recommended

 

왜 권장되지 않을까?

  1. 필드 주입은 순환참조를 막을 수 없다.
    1. a가 b를 가지고있고 b가 a를 가지고있어 순환참조를 하고잇을 경우에 실행전까지 에러를 잡을 수 없다.
  2. final 키워드를 붙일 수 없다.
    1. 변경이 가능한 순간부터 사이드이펙트가 발생할 수 있다는 것을 인지해야한다.

필드주입 생성방법

필드주입의 경우 빈들을 먼저 생성하고 애너테이션이 붙은 필드를 찾은 후 맞는 빈들을 주입하는 방식이다.

 

 

 

SetterInject

package com.example.demo.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SetterInject {

    private SetterInject2 setterInject2;

    @Autowired
    public void setSetterInject2(SetterInject2 setterInject2) {
        this.setterInject2 = setterInject2;
    }
}
package com.example.demo.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SetterInject2 {

    private SetterInject setterInject;

    @Autowired
    public void setSetterInject(SetterInject setterInject) {
        this.setterInject = setterInject;
    }
}

 

수정자 주입 방법

Setter Inject는 Field Inject와 빈 주입방식이 다르다.

주입받으려는 빈의 생성자를 호출하여 빈을 찾거나 없는경우 생성하여 컨테이너에 등록한다. 이후 주입하려는 빈 객체의 수정자를 호출하여 주입하게 된다.

 

Setter 주입은 Feild 주입과 다르게 사이클이 생기는 경우 방지된다.

 

 

그렇지만 setter를 사용하기 위해 final을 포기해야 한다는 단점이 존재한다.

 

ConstructInject

package com.example.demo.domain;

import org.springframework.stereotype.Service;

@Service
public class ConstructInject {

    private final Field1 field1;

    public ConstructInject(Field1 field1) {
        this.field1 = field1;
    }

    public Field1 getField1() {
        return field1;
    }
}
package com.example.demo.domain;

import org.springframework.stereotype.Service;

@Service
public class ConstructInject {

    private final Field1 field1;

    @Autowired
    public ConstructInject(Field1 field1) {
        this.field1 = field1;
    }

    public Field1 getField1() {
        return field1;
    }
}

 

생성자 주입 방법

생성자 주입의 경우 생성자에 필요한 인자를 먼저 확인한 후 인자에 해당하는 빈들을 먼저 생성한다.

순환참조가 발생하는 경우 여기서 걸러지게 된다.

빈들을 모두 정상적으로 만들었다면 주입하여 만들게 된다.

생성자 주입은 필드주입의 장점을 모두 해결할 수 있다.

 

  1. 순환참조 방지
  2. 불변성 보장

 

결론 : 생성자 주입을 사용하자.

추가정보 : 테스트코드 작성시 생성자 주입을 이용하면 에러가 발생한다. 이때는 필드주입으로 테스트하자.

댓글

💲 광고입니다.