[Spring] Bean 등록하기 (@Bean vs @Component) / 같은 타입의 Bean 구분하기 (@Primary vs @Qualifier())
Bean 등록하기
1. 클래스를 Bean으로 등록하기
@Component 사용
@Component
public class MyService {
public void serve() {
System.out.println("Service is serving...");
}
}
@Component를 사용하면 Spring의 @ComponentScan에 의해 자동으로 스캔되고, 클래스를 인스턴스화하여 Spring IoC 컨테이너에 등록된다. 이후 다른 곳에서 의존성 주입을 통해 해당 인스턴스를 사용할 수 있다.
(예시 : @Service, @Repository 등)
2. 메소드를 Bean으로 등록하기
@Bean 사용
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
@Bean은 @Configuration 클래스 내의 메소드 수준에서 사용된다. 객체를 직접 생성하고 Spring IoC 컨테이너에 등록할 수 있다.
결론
어떤 것을 사용하는 게 좋을까 ?
직접 작성한 Class를 Bean에 등록시키고 싶다면 ? -> @Component
외부 라이브러리에 작성되어있는 Class를 Bean에 등록시키고 싶다면 ? -> @Bean
같은 타입의 Bean 구분하기
1. 이름으로 구분하기
같은 타입의 Bean은 기본적으로 Bean의 이름으로 구분할 수 있다.
아래와 같이 Food 타입의 Pizza와 Chicken을 Bean으로 등록해두었다고 가정하자.
public interface Food {
void eat();
}
@Component
public class Pizza implements Food {
@Override
public void eat() {
System.out.println("eat pizza");
}
}
@Component
public class Chicken implements Food {
@Override
public void eat() {
System.out.println("eat Chicken");
}
}
이후 @Autowired 등으로 Bean을 주입할 때, Food 타입으로 여러개의 Bean이 등록되어있기때문에 타입만으로는 Bean을 찾을 수 없어 오류가 난다.
public Class Test{
@Autowired
Food food; //오류 발생. chicken과 pizza 중 어떤 걸 주입해야하는지 알 수 없음.
}
따라서 아래와 같이 등록된 이름을 명시해주어 해당 Bean을 주입 받아 사용할 수 있다.
public Class Test{
@Autowired
Food pizza;
@Autowired
Food chicken;
}
2. Primary로 구분하기
같은 타입의 Bean이 여러개 일 때 @Primary 어노테이션을 사용해 주입 될 Bean을 설정해줄 수 있다.
@Component
@Primary
public class Chicken implements Food {
@Override
public void eat() {
System.out.println("eat Chicken");
}
}
public Class Test{
@Autowired
Food food; //primary 설정되어있는 chicken이 주입된다.
}
3. Qualifier로 구분하기
같은 타입의 Bean이 여러개 일 때 @Qualifier 어노테이션을 사용해 주입 될 Bean을 설정해줄 수 있다.
@Component
@Qualifier("pizza")
public class Pizza implements Food {
@Override
public void eat() {
System.out.println("eat pizza");
}
}
@Component
@Primary
public class Chicken implements Food {
@Override
public void eat() {
System.out.println("eat Chicken");
}
}
public Class Test{
@Autowired
@Qualifier("pizza")
Food food; //Qualifier 설정되어있는 pizza가 주입된다.
}
위와 같이 Qualifier와 Parimary가 같이 사용되는 경우, 우선순위는 Qualifier > Primary 순이다.
결론
어떤 것을 사용하는 게 좋을까 ?
범용적으로 사용되는 Bean 객체라면 ? -> @Parimary 사용
지역적으로 사용되는 Bean 객체라면 ? -> @Qualifier 사용