객체가 다른 객체의 서비스를 이용할 때, 직접 객체를 생성하는 대신 외부에서 생성된 객체를 받아 사용하는 방식이다.
이는 클래스 간의 결합도를 낮추고, 코드의 재사용성과 테스트 용이성을 높여준다.
제네시스 클래스는 항상 Car 객체를 생성한다.
->제네시스 클래스가 Car 클래스에 의존한다고 할 수 있다.
또한 제네시스 생성자 함수에 Car 클래스의 메서드가 포함되어 있다.
-> run함수를 수정하면 제네시스 클래스의 생성자 결과도 변한다.
-> 결합도가 너무 높다. (의존성 높음)
Class Genesis {
Car car = new Car();
public Genesis() {
car.run();
}
}
스프링 컨테이너에 등록한 빈에게 의존 관계 주입이 필요할 때, DI를 도와주는 어노테이션이다. (이미 만들어진 클래스의 객체를 다시 직접 생성하지 않고 주입 받아 사용하는 것을 도와줌)
스프링 컨테이너에 빈들을 모두 등록한 뒤에 의존성 주입 단계가 실행된다.
이 때 @Autowired 어노테이션이 붙은 메서드들이 실행되며 필요한 인스턴스를 주입한다.
생성자를 통해 의존 관계를 주입한다.
객체가 생성될 때 딱 한번 호출되는 것이 보장된다.
의존 관계에 있는 객체들을 final로 선언할 수 있다.
생성자는 무조건 실행되는 메서드이므로 값이 누락될 일이 없다.
(final 키워드를 사용하면 객체가 생성될 때 한 번만 값이 할당되고, 이후에는 변경이 불가함
->따라서 의존 관계가 변하지 않는 경우, 필수 의존 관계에서 사용)
@Component
public class MyService {
private final SomeDependency someDependency; // ✅ final 선언 가능
@Autowired
public MyService(SomeDependency someDependency) {
this.someDependency = someDependency; // 🔥 생성자를 통해 반드시 값이 할당됨
}
public void doSomething() {
someDependency.execute();
}
}
setter를 생성하고, 그 위에 @Autowired를 붙인다.
-> 객체가 생성된 이후에도 의존성 변경이 가능하다.
스프링 빈을 모두 등록한 후에 해당 어노테이션이 붙은 setter를 모두 찾아 의존 관계를 주입해준다.
선택적이고, 변화 가능한 의존 관계에 사용한다.
@Component
public class MyService {
private SomeDependency someDependency;
@Autowired
public void setSomeDependency(SomeDependency someDependency) {
this.someDependency = someDependency;
}
public void doSomething() {
someDependency.execute();
}
}
제일 간단한 방법
변수에 @Aurowired 붙여서 사용
(간단하지만 단점이 너무 많아서 어플리케이션과 상관없는 테스트 코드에서 사용하는 것을 추천)
@RestController
public class FieldInjectionController{
@Autowired
private MyService myService;
}