본문 바로가기
SpringBoot

spring factory pattern

by ByteBridge 2020. 10. 19.
반응형

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();
  }
}

 

git repository

반응형

'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