스프링에서 의존성을 주입하는 방법은 3가지가 있다.
@Component
public class Dewcoding {
private final Dew dew;
public DewCoding(Dew dew){
this.dew = dew;
}
}
단일 생성자의 경우 @Autowired
어노테이션을 붙이지 않아도 되지만, 생성자가 2개 이상인 경우에는 생성자에 @Autowired
어노테이션을 붙여줘야 한다.
@Component
@RequiredArgsConstructor
public class Dewcoding {
private final Dew dew;
}
@RequiredArgsConstructor
어노테이션은 final
이나 @NotNull
을 사용한 필드에 대한 생성자를 자동으로 생성해준다.
@Component
public class Dewcoding {
@Autowired
private Dew dew;
}
생성자 주입과 달리 필드를 final
선언할 수 없다.
@Component
public class Dewcoding {
private Dew dew;
@Autowired
public void setDew(Dew dew){
this.dew = dew;
}
}
생성자 주입이 아닌 다른 방식으로 주입하면 인텔리제이는 다음과 같은 경고를 준다.
Spring Team recommends: "Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencied".
대충 생성자 주입 방식
을 추천한다는 뜻.
객체의 의존성을 추가하다 보면 순환 참조 문제가 발생할 수 있다.
순환 참조
란 A가 B를 참조하면서, B도 A를 참조하는 경우 발생한다.
@Component
public class Dew{
@Autowired
private Coding coding;
public void dew(){
coding.coding();
}
}
@Component
public class Coding{
@Autowired
private Dew dew;
public void coding(){
dew.dew();
}
}
Dew
와 coding
의 빈을 하나씩 생성 후, 서로 필드 주입한고 이 둘을 DewCoding
에 주입한다.
@Component
public class DewCoding{
@Autowired
private Dew dew;
@Autowired
private Coding coding;
public void dewCoding() {
dew.dew();
coding.coding();
}
}
서버를 실행 한 후 dewCoding()
메서드가 나오면 순환참조로 서버가 다운된다.
메소드 실행 전까지는 순환 참조가 있는걸 알 수 없다.
따라서 순환 참조를 방지하기 위해서는 생성자 주입을 해야한다.
위의 예제를 생성자 주입으로 변경하면 다음과 같다.
@Component
@RequiredArgsConstructor
public class Dew{
private final Coding coding;
public void dew(){
coding.coding();
}
}
@Component
@RequiredArgsConstructor
public class Coding{
private final Dew dew;
public void coding(){
dew.dew();
}
}
@Component
@RequiredArgsConstructor
public class DewCoding{
private final Dew dew;
private final Coding coding;
public void dewCoding(){
dew.dew();
coding.coding();
}
}
생성자 주입으로 변경하게 되면 순환 참조가 있을 때 서버 자체가 구동 되지 않는다.
생성자 주입 방식은 필드와 수정자 방식가 다르게 먼저 빈을 생성하지 않고 주입하려는 빈을 먼저 찾기 때문에 참조하는 객체가 생성되지 않은 상태에서 그 빈을 참조하기 때문에 오류가 발생하는 것이다.
필드를 final
로 선언할 수 있기 때문에 런타임에 객체 불변성을 보장한다.
스프링 컨테이너 도움 없이 테스트 코드를 더 편리하게 작성할 수 있다.
테스트하고자 하는 클래스에 필드 주입이나 수정자 주입으로 빈이 주입되어 있으면, Mockito
를 이용해 목킹한 후 테스트를 진행해야 한다.
하지만, 생성자 주입의 경우는 단순히 원하는 객체를 생성한 후, 생성자에 넣어주면 된다.
public class DewTest{
@Test
public void test(){
Dew dew = new Dew();
DewCoding dewCoding = new DewCoding(dew);
dew.dew();
}
}