ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring factory pattern
    Tech/SpringBoot 2020. 10. 19. 23:46
    반응형

    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

    반응형

    'Tech > 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
Designed by Tistory.