복붙노트

[SPRING] 스프링 부트 내의 전략

SPRING

스프링 부트 내의 전략

안녕하세요 저는 스프링 부트 응용 프로그램에서 전략 패턴을가집니다. 모든 전략에는 자동 생성자가 있습니다. 나는 봄 부츠를 처음 사용합니다. 가장 간단한 아이디어가 없습니다. autowired 생성자가 의존성을 주입 한 것처럼 전략 클래스 용으로 내 공장을 작성하려면 어떻게해야합니까? 나는 이것으로 얻는 어떤 도움을 주셔서 감사합니다.

참고 : 샘플을 혼란스럽게하지 않기 위해 인터페이스와 기본 클래스를 생략하고 있습니다.

public class StrategyA implement Strategy {
private DependencyA depA;
private DependencyB depB;
   @Autowired
   public StragegyA(DependencyA depA, DependencyB depB) {
       this.depA = depA;
       this.depB = depB;
   }
}

public class StrategyB implements Strategy {
private DependencyA depA;
private DependencyB depB;
   @Autowired
   public StragegyB(DependencyA depA, DependencyB depB) {
       this.depA = depA;
       this.depB = depB;
   }
}

public class StrategyFactory {
    public Strategy getStrategy(String strategyName) {
      if (name.equals("StrategyA")) {
         <b>return StrategyA; //My problem is here
      } else {
         return StrategyB; // And Here
      }
    }
}

해결법

  1. ==============================

    1.이전 답변은 모두 봄용 DI를 사용했습니다. 그러나 FactoryLocatorFactoryBean을 사용하여 공장에서 빈을 지정하지 않고도 팩토리를 생성 할 수 있습니다. 먼저 팩토리에 대한 인터페이스를 정의하십시오.

    이전 답변은 모두 봄용 DI를 사용했습니다. 그러나 FactoryLocatorFactoryBean을 사용하여 공장에서 빈을 지정하지 않고도 팩토리를 생성 할 수 있습니다. 먼저 팩토리에 대한 인터페이스를 정의하십시오.

    public interface MyFactory {
        Strategy get(String type);
    }
    
    // Could be an abstract class
    public interface Strategy {
        void doStuff();
    }
    

    그런 다음 응용 프로그램에서 :

    @Configuration
    public class AppConfiguration {
        @Autowired
        private BeanFactory beanFactory;
    
        public ServiceLocatorFactoryBean myFactoryLocator() {
            final ServiceLocatorFactoryBean locator = new ServiceLocatorFactoryBean();
            locator.setServiceLocatorInterface(MyFactory.class);
            locator.setBeanFactory(beanFactory);
            return locator;
        }
    
        @Bean
        public MyFactory myFactory() {
            final ServiceLocatorFactoryBean locator = myFactoryLocator();
            locator.afterPropertiesSet();
            return (MyFactory) locator.getObject();
        }
    }
    

    이제는 / extends를 구현하는 bean (@Service, @Component 또는 @Bean 주석 사용)을 정의 할 수 있으며 MyFactory 빈에 자동으로 등록되며 다음을 사용하여 만들 수 있습니다.

    myFactory.get("beanName");
    

    가장 좋은 점은 전략 빈을 게으르고 다른 범위로 등록 할 수 있다는 것입니다.

  2. ==============================

    2.StrategyFactory를 다른 Spring 빈으로 만들고 모든 전략을 팩토리에 삽입하십시오.

    StrategyFactory를 다른 Spring 빈으로 만들고 모든 전략을 팩토리에 삽입하십시오.

    @Component
    public class StrategyFactory {
        private final List<Strategy> strategies;
    
        @Autowired
        public StrategyFactory(List<Strategy> strategies) {
            this.strategies = strategies;
        }
    
        public Strategy getStrategy(String strategyName) {
            // iterate through the strategies to find the right one, and return it.
        }
    }
    

    일반적으로 문자열 대신 열거 형을 사용하여 전략을 식별하고 각 전략에서 처리하는 열거 형 값을 반환하도록합니다. 따라서 반복은 다음과 같이 간단 할 수 있습니다.

    return strategies.stream().filter(strategy -> strategy.getType() == type).findAny().orElseThrow(
        () -> new IllegalStateException("No strategy found for type " + type));
    

    물론, 생성자 안의 Map에 전략을 저장하여 조회 O (1)를 만들 수도 있습니다.

  3. ==============================

    3.StrategyFactory를 빈으로 만들고 Map 을 삽입하도록 제안합니다. Spring은 전략 빈의 이름을 키로 채우고 값은 전략 그 자체 일 것이다. 그럼 당신이해야 할 일은 그지도에 전화하는 것입니다.

    StrategyFactory를 빈으로 만들고 Map 을 삽입하도록 제안합니다. Spring은 전략 빈의 이름을 키로 채우고 값은 전략 그 자체 일 것이다. 그럼 당신이해야 할 일은 그지도에 전화하는 것입니다.

    다음은 그 예입니다.

    @SpringBootApplication
    public class So44761709Application {
    
        public static void main(String[] args) {
            SpringApplication.run(So44761709Application.class, args);
        }
    
        public interface Strategy { }
    
        @Component
        public static class DependencyA {}
        @Component
        public static class DependencyB {}
    
        @Component("StrategyA")
        public static class StrategyA implements Strategy {
            private DependencyA depA;
            private DependencyB depB;
            @Autowired
            public StrategyA(DependencyA depA, DependencyB depB) {
                this.depA = depA;
                this.depB = depB;
            }
        }
    
        @Component("StrategyB")
        public class StrategyB implements Strategy {
            private DependencyA depA;
            private DependencyB depB;
            @Autowired
            public StrategyB(DependencyA depA, DependencyB depB) {
                this.depA = depA;
                this.depB = depB;
            }
        }
    
        @Component
        public class StrategyFactory {
            @Autowired
            private Map<String, Strategy> strategies;
    
            public Strategy getStrategy(String strategyName) {
                return strategies.get(strategyName);
            }
        }
    
        @Bean
        CommandLineRunner run(StrategyFactory strategyFactory) {
            return args -> {
                System.out.println(strategyFactory.getStrategy("StrategyB").getClass().getSimpleName());
                System.out.println(strategyFactory.getStrategy("StrategyA").getClass().getSimpleName());
            };
        }
    }
    

    인쇄물:

    StrategyB
    StrategyA
    
  4. ==============================

    4.

    @Component
    public class StrategyFactory {
        private StrategyA sA;
        private StrategyB sB;
        @Autowired
        public StrategyFactory (StrategyA sA, StrategyB sB) {
            this.sA = sA;
            this.sB = sB;
        }
        public Strategy getStrategy(String strategyName) {
          if (name.equals("StrategyA")) {
             return sA; //My problem is here
          } else {
             return sB; // And Here
          }
        }
    }
    

    모든 전략을 자동 와이어 링하는 것과 동일한 접근 방식을 사용하십시오.

  5. from https://stackoverflow.com/questions/44761709/strategy-within-spring-boot by cc-by-sa and MIT license