티스토리 뷰
Spring 에서 여러 객체를 @Autowired 로 array, List, Set, Map 으로 주입받기
zepinos 2019. 8. 9. 15:20Spring 에서 흔히 @Autowired 로 객체를 주입받을 때 아래와 같이 사용합니다.
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
그러면 BCryptPasBCryptPasswordEncoder 을 Singleton 으로 생성(new)해서 사용하는 것과 같은 효과를 얻을 수 있습니다.
그런데, 간혹 Interface 을 구현(Implement)한 객체 여러개를 주입받고 상황에 따라 그 중 하나를 사용하고 싶을 때에는 어떻게 해야 할까요? 보통은 ApplicationContext#getBean 을 이용해서 등록된 Bean 중 하나를 꺼내서 사용할 것입니다.
passwordEncoder = (PasswordEncoder) applicationContext.getBean("bCryptPasswordEncoder");
하지만, 사실 다른 방법도 존재합니다.
예를 들어 PasswordEncoder Interface 을 구현해 만든 Pbkdf2Pbkdf2PasswordEncoder Class 와 Spring Security 에서 제공하는 BCryptPasswordEncoder 을 array 나 List, Map 형태로 받아서 선택해서 사용하려고 한다고 하면 어떻게 해야 할까요?
먼저, Pbkdf2PasswordEncoder Class 은 다음과 같이 만듭니다. (secret 와 iteration, keylength 는 생략하겠습니다)
@Component
public class Pbkdf2PasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
try {
byte[] result = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512")
.generateSecret(new PBEKeySpec(charSequence.toString().toCharArray(), secret.getBytes(), iteration, keylength))
.getEncoded();
return Base64.getEncoder().encodeToString(result);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
return null;
}
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return encode(charSequence).equals(s);
}
}
이렇게만 구현해두면 PasswordEncoder 을 이용해서도 단독으로 주입받을 수 있습니다.
@Autowired
private PasswordEncoder passwordEncoder;
이번에는 BcryptPasswordEncoder 을 주입받을 수 있도록 MyBcryptPasswordEncoder Class 을 만들어보겠습니다.
@Primary
@Component
public class MyBcryptPasswordEncoder implements PasswordEncoder {
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public MyBcryptPasswordEncoder() {
this.bCryptPasswordEncoder = new BCryptPasswordEncoder();
}
@Override
public String encode(CharSequence charSequence) {
return bCryptPasswordEncoder.encode(charSequence);
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return bCryptPasswordEncoder.matches(charSequence, s);
}
}
주의할 것은 @Primary 입니다. 앞서 구현한 Pbkdf2PasswordEncoder 와 MyBcryptPasswordEncoder 모두 PasswordEncoder 에 대한 구현체입니다. 그렇기 때문에 이 둘을 Component 로 등록하는 순간 충돌이 발생합니다(NoUniqueBeanDefinitionException). 그렇기 때문에 우선순위를 두어서 단독으로 사용할 경우 주입받을 우선순위를 정해주는 것입니다.
이렇게 생성한 뒤, 아래와 같이 PasswordEncoder 을 주입받아 보겠습니다.
@Autowired
private Map<String, PasswordEncoder> passwordEncoderMap;
그러면, Component 로 등록한 두 개의 Class 을 Map 으로 주입해주는 것을 알 수 있습니다. 당연히 Map 의 key 은 Bean Name 이 들어갑니다. 그래서 각각 myBcryptPasswordEncoder, pbkdf2PasswordEncoder 가 key 입니다.
array 나 List, Set 은 key 없이 입력되기 때문에 더 이상 설명은 필요 없을 것 같습니다.
'Programming > Java' 카테고리의 다른 글
Spring Boot 을 언제 써야 할까? (0) 프롤로그 (0) | 2019.09.18 |
---|---|
MSA 구성을 위한 기술 (0) | 2019.09.10 |
Tomcat 에 배포되던 소스를 JBoss(Wildfly) 에 배포 (0) | 2019.07.23 |
내장 Tomcat 와 외장 Tomcat 의 간단한 비교 (0) | 2019.02.22 |
Undertow 와 Tomcat 의 간단한 비교 (4) | 2019.02.22 |
- Total
- Today
- Yesterday
- couchbase
- 외장 WAS
- Nas
- 내장 WAS
- jooq
- 페이징
- Phabricator
- RestTemplate
- git
- SI
- OracleJDK
- 엘지
- Spring
- 프로젝트 규모
- manjaro
- boot
- proxmox
- messages.properties
- java config
- paging
- 시니어 프로그래머
- docker
- 클라우드플레어
- 워드프레스
- Spring Boot
- KDE
- NoSQL
- Redmine
- Spring MVC
- 도입기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |