반응형
Factory 패턴:
하위 클래스가 어떤 객체를 생성할지를 결정 하도록 하는 패턴.
스프링에서 빈을 컬렉션으로 주입할 수 있다.
//타입
public enum AuthenticationType {
PASSWORD, DEVICE, FIDO
}
//인터페이스
public interface AuthenticationService {
AuthenticationType getAuthentiicationType();
void validateAuthentication();
}
//비밀번호 인증구현체
@Slf4j
@Service
public class AuthenticationPasswordService implements AuthenticationService{
@Override
public AuthenticationType getAuthentiicationType() {
return AuthenticationType.PASSWORD;
}
@Override
public void validateAuthentication() {
log.info("==================> password validation");
}
}
//디바이스 인증 구현체
@Slf4j
@Service
public class AuthenticationDeviceService implements AuthenticationService{
@Override
public AuthenticationType getAuthentiicationType() {
return AuthenticationType.DEVICE;
}
@Override
public void validateAuthentication() {
log.info("==================> devicee validation");
}
}
//Fido 인증 구현체
@Slf4j
@Service
public class AuthenticationFidoService implements AuthenticationService{
@Override
public AuthenticationType getAuthentiicationType() {
return AuthenticationType.FIDO;
}
@Override
public void validateAuthentication() {
log.info("==================> FIDO validation");
}
}
//팩토리
@Component
public class AuthenticationFactory {
private final Map<AuthenticationType, AuthenticationService> authenticationServiceMap = new HashMap<>();
//생성자 주입으로 인증서비스를 상송하고 있는 bean 들을 주입
public AuthenticationFactory(List<AuthenticationService> authenticationServiceList) {
// if not found authentication bean -> exception
if (ObjectUtils.isEmpty(authenticationServiceList)) {
throw new IllegalArgumentException("Not found service");
}
for (AuthenticationService authenticationService : authenticationServiceList) {
this.authenticationServiceMap
.put(authenticationService.getAuthentiicationType(), authenticationService);
}
}
public AuthenticationService getAuthenticationService(AuthenticationType type) {
// 타입에 해당하는 인증서비스의 bean return
return authenticationServiceMap.get(type);
}
//factory 사용
@RestController
@RequestMapping("/auth")
public class AuthenticationController {
private final AuthenticationFactory authenticationFactory;
public AuthenticationController(
AuthenticationFactory authenticationFactory) {
this.authenticationFactory = authenticationFactory;
}
@PostMapping("/validation")
public AuthRes authValidate(@RequestBody AuthReq authReq){
authenticationFactory.getAuthenticationService(authReq.getAuthType()).validateAuthentication();
return AuthRes.builder()
.code(authReq.getAuthType().name())
.message("success")
.build();
}
}
// 팩토리를 통한 타입별 인증 서비스 로딩 테스트
@SpringBootTest
class AuthenticationFactoryTest {
@Autowired
private AuthenticationFactory authenticationFactory;
@Test
void 타입별_인증_서비스_로딩_테스트(){
//given
AuthenticationType passwordType = AuthenticationType.PASSWORD;
AuthenticationType fidoType = AuthenticationType.FIDO;
AuthenticationType deviceType = AuthenticationType.DEVICE;
//when
AuthenticationService passwordAuthenticationService = authenticationFactory.getAuthenticationService(passwordType);
AuthenticationService fidoAuthenticationService = authenticationFactory.getAuthenticationService(fidoType);
AuthenticationService deviceAuthenticationService = authenticationFactory.getAuthenticationService(deviceType);
//then
assertEquals(passwordAuthenticationService.getAuthentiicationType(),AuthenticationType.PASSWORD);
assertEquals(fidoAuthenticationService.getAuthentiicationType(),AuthenticationType.FIDO);
assertEquals(deviceAuthenticationService.getAuthentiicationType(),AuthenticationType.DEVICE);
// show
passwordAuthenticationService.validateAuthentication();
fidoAuthenticationService.validateAuthentication();
deviceAuthenticationService.validateAuthentication();
}
}
반응형
'SpringBoot' 카테고리의 다른 글
ModelMapper 를 사용하여 객체 컨버팅 하기 (0) | 2021.05.23 |
---|---|
Spring AOP (0) | 2020.12.06 |
spring webflux swagger config (0) | 2020.08.31 |
React Stream create and test (0) | 2020.08.24 |
Spring boot kafka demo with docker-compose (0) | 2020.07.20 |