Bean의 생성, 초기화는 Spring framework가 해줍니다.
이 때 생성, 초기화 과정에서 필요한 의존성을 Spring framework가 찾아 주입해줍니다.
생성은 객체가 new 연산자를 통해 생성된 것이며 초기화는 해당 객체에 필요한 의존성을 갖추는 것을 의미합니다.
class Example {
private String a;
public void setA(String given) {
this.a = given;
}
}
Example example = new Example(); // 생성
example.setA("hello"); // 초기화
@Autowired 어노테이션을 사용하여 클래스의 필드에 직접 의존성을 주입합니다.
public class Service {
@Autowired
private Dependency dependency;
}
단점
IntelliJ에서는 필드 주입을 사용하면 "Field Injection is not recommended"라는 경고문을 띄우고, 스프링 공식 레퍼런스에는 소개조차 되지 않습니다.
의존성이 필요한 필드에 대해 setter 메서드를 정의하고 Spring 컨테이너가 이 메서드를 호출하여 의존성을 주입합니다.
public class Service {
private Dependency dependency;
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
}
장점
단점
의존성을 필요한 필드를 생성자의 매개변수로 받아들이고, 이를 통해 주입을 받습니다. Spring 4.3부터는 생성자가 하나만 있을 경우 @Autowired 어노테이션을 생략할 수 있습니다.
public class Service {
private final Dependency dependency;
@Autowired // 생략 가능
public Service(Dependency dependency) {
this.dependency = dependency;
}
}
@Service
public class Service {
private final Dependency1 dependency1;
private final Dependency2 dependency2;
public Service(Dependency1 dependency1) {
this.dependency1 = dependency1;
this.dependency2 = null;
}
@Autowired // 생략 불가
public Service(Dependency1 dependency1, Dependency2 dependency2) {
this.dependency1 = dependency1;
this.dependency2 = dependency2;
}
}
생성자가 두 개 이상인 경우 반드시 1개의 생성자에
@Autowired를 명시해주어야 합니다.Spring은 @Autowired가 붙은 생성자를 통해 의존성을 주입합니다. 따라서 두 생성자에 모두 @Autowired를 붙이면 Spring이 어느 생성자를 사용할지 혼란스러워 할 수 있으며, 이는 예외를 발생시킬 수 있습니다.
장점
단점
@RequiredArgsConstructor를 통해 해결할 수 있습니다.불변 객체(Immutable Object)는 객체가 생성된 후 그 상태를 변경할 수 없는 객체를 의미합니다.
Spring은 multi-thread 환경에서 작동되며 각 Bean들은 Singletone으로 관리되어 재사용됩니다.
Singletone으로 관리되는 객체의 경우 상태를 가지게 되면 이전 호출에서 가졌던 상태가 이후 호출에서 영향을 미치게 됩니다.
이런 상황에서 muli-thread 환경까지 겹치게 되면 개발자는 상태 추적(예상, 관리)가 불가능할 수 있습니다.
As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans.
from Spring docs