
스프링 개발을 하다 보면 동일한 타입의 Bean이 여러 개 존재하는 경우가 많습니다. 이때 스프링이 어떤 Bean을 주입해야 할지 알 수 없기 때문에 오류가 발생하게 됩니다. 이러한 상황에서 특정 Bean을 명확하게 지정하기 위해 사용하는 것이 @Qualifier입니다.
@Qualifier는 스프링에서 의존성 주입을 수행할 때, 동일한 타입의 Bean이 여러 개일 경우 어떤 Bean을 사용할지 명시적으로 지정하는 어노테이션입니다.
스프링이 자동 주입(@Autowired)을 시도할 때 같은 타입의 Bean이 여러 개 있으면 선택을 하지 못해 예외가 발생합니다. 이때 @Qualifier("beanName")으로 Bean을 지정해주면 문제를 해결할 수 있습니다.
아래와 같이 두 개의 DataSource Bean을 정의했다고 가정해보겠습니다.
@Bean("mainDataSource")
public DataSource mainDataSource() { ... }
@Bean("logDataSource")
public DataSource logDataSource() { ... }
이 상태에서 의존성 주입을 다음과 같이 작성하면 오류가 발생합니다.
@Autowired
private DataSource dataSource;
DataSource 타입의 Bean이 2개이므로 어떤 것을 주입해야 할지 결정할 수 없기 때문입니다.
@Configuration
public class MultiDataSourceConfig {
@Bean("mainDataSource")
public DataSource mainDataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.url("jdbc:mysql://localhost:3306/main_db")
.username("main_user")
.password("main_pw")
.build();
}
@Bean("logDataSource")
public DataSource logDataSource() {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.url("jdbc:mysql://localhost:3306/log_db")
.username("log_user")
.password("log_pw")
.build();
}
}
@Service
public class LogService {
private final DataSource logDataSource;
@Autowired
public LogService(@Qualifier("logDataSource") DataSource logDataSource) {
this.logDataSource = logDataSource;
}
public void writeLog(String message) {
// 로그 DB 저장 처리
}
}
위 코드에서 @Qualifier("logDataSource")는 logDataSource라는 이름의 Bean을 명확히 지정하여 주입하도록 합니다.
MyBatis 설정, 트랜잭션 설정 등에서도 동일하게 사용됩니다.
@Bean("logSqlSessionFactory")
public SqlSessionFactory logSqlSessionFactory(
@Qualifier("logDataSource") DataSource logDataSource
) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(logDataSource);
return factory.getObject();
}
파라미터로 어떤 Bean이 들어갈지 명시적으로 지정해야 혼선 없이 Factory가 생성됩니다.
@Primary는 기본적으로 주입될 Bean을 지정하는 방식이고,
@Qualifier는 특정 Bean을 선택적으로 사용하고 싶을 때 지정하는 방식입니다.
@Primary
@Bean("mainDataSource")
public DataSource mainDataSource() { ... }
@Bean("logDataSource")
public DataSource logDataSource() { ... }
이 경우 기본적으로 mainDataSource가 사용되지만, 필요한 곳에서는 다음처럼 선택할 수 있습니다.
@Autowired
@Qualifier("logDataSource")
private DataSource logDataSource;
@Qualifier는 동일한 타입의 Bean이 여러 개 있을 때 어떤 Bean을 사용할지 명확히 지정하기 위해 사용하며, 멀티 데이터소스 환경에서 필수적으로 사용되는 개념입니다.
@Primary와 함께 사용하면 기본 Bean과 선택적 Bean을 유연하게 구성할 수 있습니다.