아님 뭐 메서드 내 필드를 이용해서 이렇게 바꿀까? 이것도 뭐 크게 다른건 없다고 느끼는데, 그렇다고 싱글톤 기반의 빈에서 클래스 필드를 맘대로 교체할 수도 없는 노릇이고,
좀 더 고차원 레이어에 영향이 안가는 방법의 코드를 작성 할 수는 없을까?
있다, Enum과 Provider를 사용하면 된다. Spring Container는 등록된 모든 Bean에 대한 제어가 가능하다. 일단 등록되어 있으니 가져오는 것도 가능하다. 구조적으로는 위에 if문을 사용하는 것과 차이가 없지만,
적어도 인터페이스를 호출 하는 부분을 타입이나, 유형 때문에 바꿀 일은 없을 거다.
예시 코드 들어간다.
참고로 제 코드가 좋은 코드는 아닙니다용..제발...
public interface PayService {
void pay();
}
private class PayKakaoService implements PayService {
@Override
public void pay() {
}
}
private class PaySamsungService implements PayService {
@Override
public void pay() {
}
}
private class PayNaverService implements PayService {
@Override
public void pay() {
}
}
// private PayService payKakaoService;
// private PayService paySamsungService;
// private PayService payNaverService;
@Getter
@RequiredArgsConstructor
public enum PayType {
Kakao(PayKakaoService.class), Samsung(PaySamsungService.class), Naver(
PayNaverService.class);
private final Class<? extends PayService> clazz;
}
public class PayServiceProvider {
private static ApplicationContext applicationContext;
private static Map<PayType, Class<? extends PayService>> payServiceMap = new HashMap<>();
static {
for (PayType payType : PayType.values()) {
payServiceMap.put(payType, payType.getClazz());
}
}
public static PayService service(PayType payType) throws Exception {
Class<? extends PayService> payServiceClass = payServiceMap.get(payType);
if (payServiceClass == null) {
throw new Exception();
}
return applicationContext.getBean(payServiceClass);
}
}
@PostMapping("/payment")
public ResponseEntity<?> pay(PayType payType) throws Exception {
// PayService ps = null;
//
// if (payType == PayType.Kakao) {
// ps = payKakaoService;
// }
//
// if (payType == PayType.Samsung) {
// ps = paySamsungService;
// }
//
// if (payType == PayType.Naver) {
// ps = payNaverService;
// }
//
// ps.pay();
PayServiceProvider.service(payType).pay();
return ResponseEntity.ok().build();
}
// 실행
void callPayTest() throws Exception {
this.pay(PayType.Samsung);
}
일단, 해당 코드는 provider에서 사용하는 applicationContext에 대한 주입이 없긴하다. 요건 이제 @PostConstruct를 사용해서 주입하면 되긴합니다요. 물론 주입하는 함수도 provider에 static으로 만들어 줘야 합니다. (대충 읽고 코드만 복붙하면 안되게 하려는 함정...)
-- 계정 생성
> create user ${User}@${Host} identified by ${Password}
-- User = login id
-- Host = remote ip | '%' (all)
-- Password = 486 (윤하...)
(하루에 네번 사랑을 말하고...여덟번 웃고...여섯번의...)
-- 모든 권한 부여
> grant all privileges on ${DB}.${Table} TO ${User}@${Host}
-- option identified by ${Password};
-- option 적용시 비밀번호 바뀜
-- DB = 적용할 Database ( possible * )
-- Table = 적용할 Table ( possible * )
-- 권한 적용
> flush privileges
-- 권한 확인
> show grants for ${User}@${Host}