오늘은 같은 타입의 빈이 여러 개인 경우 식별하는 방법을 포스팅한다.
주제는 빈을 식별하는 방법으로 코드의 내용은 신경쓰지 않고 단순히 구분을 위해 작성했다.
public interface MailService {
void sendEmail(String email);
}
@Service
public class NaverMailServiceImpl implements MailService {
@Override
public void sendEmail(String email) {
System.out.println("Send naver mail to " + email);
}
}
@Service
public class GoogleMailServiceImpl implements MailService {
@Override
public void sendEmail(String email) {
System.out.println("Send google mail to" + email);
}
}
@Service
public class UserService {
private final MailService mailService;
public UserService(MailService mailService) {
this.mailService = mailService;
}
public String createUser(SignUpDto signUpDto) {
// ... create user
return mailService.sendEmail(signUpDto.getEmail());
}
}
우리가 어떠한 문제를 해결하기 위해 다형성을 이용하여 의존성을 주입받는 경우가 있다. 위의 경우 mailService 인터페이스를 특정 구현체를 상속받아 서비스를 이용하게 될 것인데, 여러 타입의 빈이 존재하는 상황에서 스프링은 의존성을 어떻게 식별할 수 있을까?
field name
첫 번째는 바로 이름으로 식별하는 방법이다.
스프링은 의존성 주입 시 타입을 찾으면서 두 개 이상의 같은 빈을 가지는 경우, 필드 이름(Autowired) 그리고 파라미터의 이름(constructor)을 통해 한 번 더 찾는다.
@Service
public class UserService {
private final MailService mailService;
public UserService(MailService naverMailServiceImpl) {
this.mailService = naverMailServiceImpl; // 파라미터를 실제 구현체 클래스 이름과 같도록 작성
}
public String createUser(SignUpDto signUpDto) {
// ... create user
return mailService.sendEmail(signUpDto.getEmail());
}
}
@Service
public class UserService {
@Autowired
private MailService naverMailServiceImpl;
public String createUser(SignUpDto signUpDto) {
// ... create user
return naverMailServiceImpl.sendEmail(signUpDto.getEmail());
}
}
테스트
@SpringBootTest
class UserServiceTest {
@Autowired
UserService subject;
@Test
void 필드명으로_빈을_식별한다() {
SignUpDto userDto = SignUpDto.builder()
.name("woogie")
.email("rxjw95@gmail.com")
.build();
String response = subject.createUser(userDto);
assertEquals(response, "Send naver mail to rxjw95@gmail.com");
}
}
@Primary
두 번째는 @Primary 어노테이션을 사용하면 된다. 이름과 같이 해당 어노테이션이 붙으면 가장 먼저 빈으로 주입하게 된다.
@Primary
@Service
public class NaverMailServiceImpl implements MailService {
@Override
public String sendEmail(String email) {
return "Send naver mail to " + email;
}
}
@Service
public class UserService {
private final MailService mailService;
public UserService(MailService mailService) {
this.mailService = mailService;
}
public String createUser(SignUpDto signUpDto) {
// ... create user
return mailService.sendEmail(signUpDto.getEmail());
}
}
테스트
@SpringBootTest
class UserServiceTest {
@Autowired
UserService subject;
@Test
void Primary_어노테이션으로_빈을_식별한다() {
SignUpDto userDto = SignUpDto.builder()
.name("woogie")
.email("rxjw95@gmail.com")
.build();
String response = subject.createUser(userDto);
assertEquals(response, "Send naver mail to rxjw95@gmail.com");
}
}
@Qualifier
마지막은 @Qualifier 어노테이션을 사용하는 방법이다. 해당 어노테이션도 이름을 보고 알 수 있듯이 식별자를 두어 빈을 식별할 수 있다.
파라미터로 받을 빈과 해당 빈을 선언한 클래스에 모두 작성해주어야 한다.
@Qualifier("naver")
@Service
public class NaverMailServiceImpl implements MailService {
@Override
public String sendEmail(String email) {
return "Send naver mail to " + email;
}
}
@Service
public class UserService {
private final MailService mailService;
public UserService(@Qualifier("naver") MailService mailService) {
this.mailService = mailService;
}
public String createUser(SignUpDto signUpDto) {
// ... create user
return mailService.sendEmail(signUpDto.getEmail());
}
}
테스트
@SpringBootTest
class UserServiceTest {
@Autowired
UserService subject;
@Test
void Qualifier_어노테이션으로_빈을_식별한다() {
SignUpDto userDto = SignUpDto.builder()
.name("woogie")
.email("rxjw95@gmail.com")
.build();
String response = subject.createUser(userDto);
assertEquals(response, "Send naver mail to rxjw95@gmail.com");
}
}
@Qualifier("naver")
@Service
public class NaverMailServiceImpl implements MailService {
@Override
public String sendEmail(String email) {
return "Send naver mail to " + email;
}
}
'Spring' 카테고리의 다른 글
Unit test naming convention (0) | 2022.11.15 |
---|---|
Tomcat과 Spring의 상호작용 (0) | 2022.11.15 |
RequestParam으로 List 형식 받기 (0) | 2022.07.07 |
스프링 프레임워크 핵심 기술 - IoC 컨테이너와 Bean (0) | 2022.04.28 |
@Valid, @NotNull, @NotEmpty, @NotBlank 그리고 @NonNull (0) | 2022.04.27 |