스프링 빈에서 생성자가 한개일 경우 @Autowired를 생략할 수 있다. 그리고 롬복(lombok) 라이브러리를 사용하면 생성자도 생략할 수 있다.
// 기존 코드
@Component
public class Car{
private final String s;
@Autowired
public Car(String st){
this.s = st;
}
}
롬복 라이브러리가 제공하는 @RequiredArgsConstructor를 사용하면 final 키워드 필드를 찾아서 생성자를 자동으로 만들어준다. 생성자를 생략하면 코드 단위에서는 보이지 않지만 실제로 클래스를 열어보면 생성자가 존재한다.
// 롬복을 사용한 코드
@Component
@RequiredArgsConstructor
public class Car{
private final String s;
}
@Autowired는 생성자 주입을 자동으로 해주는데 이때 타입(Type)으로 빈을 조회한다. 그렇기 때문에 Autowired는 마치 다음 코드와 비슷하게 유사하게 동작한다.
ac.getBean(Car.class);
그래서 앞서 확인한 것 처럼 하위 타입이 두개 이상이거나 동일한 타입이 존재한다면 오류가 발생한다. 이때 스프링 빈을 수동 등록해서 문제를 해결할 수도 있고, 의존 관계 자동 주입에서 해결하는 방법도 있다.
빈 등록시 @Qualifier 라는 추가 구문자를 붙여주는 방법이다. 이것은 자동 의존 관계 주입 시 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것이 아니다.
// 빈 등록시 @Qualifer(이름)
@Component
@Qualifier("main")
public class Bmw implements Car{}
@Component
@Qualifier("sub")
public class Audi implements Car{}
//생성자 주입
@Autowired
public CarService(@Qualifier("main") Car car){
this.car = car;
}
@Primary는 우선순위를 정한다. @Autowired 시 여러 빈이 매칭되면 @Primary가 우선권을 가진다.
@Component
@Primary
public class Bmw implements Car{}
@Component
public class Audi implements Car{}
중복된 빈 중에서 하나만 선택하는 것이 아니라 모든 빈이 필요할 경우 List나 Map으로 받을 수 있다.
public class CarService {
private final Map<String, Car> carMap;
private final List<Car> cars;
@Autowired
public CarService(Map<String, Car> carMap, List<Car> cars){
this.carMap = carMap;
this.cars = cars;
}
}
해당하는 타입의 스프링 빈이 없으면 빈 리스트, Map을 주입한다.