복붙노트

[SPRING] 콩을 열거 형에 넣는다.

SPRING

콩을 열거 형에 넣는다.

보고서의 데이터를 준비하는 DataPrepareService가 있으며 보고서 형식이 Enum이고 Enum에 ReportService를 삽입하거나 열거 형에서 ReportService에 액세스해야합니다.

내 봉사 :

@Service
public class DataPrepareService {
    // my service
}

내 enum :

public enum ReportType {

    REPORT_1("name", "filename"),
    REPORT_2("name", "filename"),
    REPORT_3("name", "filename")

    public abstract Map<String, Object> getSpecificParams();

    public Map<String, Object> getCommonParams(){
        // some code that requires service
    }
}

나는 사용하려고 시도했다.

@Autowired
DataPrepareService dataPrepareService;

,하지만 작동하지 않았다.

열거 형 서비스에 내 서비스를 어떻게 삽입 할 수 있습니까?

해결법

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

    1.

    public enum ReportType {
    
        REPORT_1("name", "filename"),
        REPORT_2("name", "filename");
    
        @Component
        public static class ReportTypeServiceInjector {
            @Autowired
            private DataPrepareService dataPrepareService;
    
            @PostConstruct
            public void postConstruct() {
                for (ReportType rt : EnumSet.allOf(ReportType.class))
                   rt.setDataPrepareService(dataPrepareService);
            }
        }
    
    [...]
    
    }
    

    주말의 답은 내부 수업을 정적으로 변경하면 봄이 볼 수 있습니다.

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

    2.어쩌면 이런 식으로 :

    어쩌면 이런 식으로 :

    public enum ReportType {
        @Component
        public class ReportTypeServiceInjector {
            @Autowired
            private DataPrepareService dataPrepareService;
    
            @PostConstruct
            public void postConstruct() {
                for (ReportType rt : EnumSet.allOf(ReportType.class))
                   rt.setDataPrepareService(dataPrepareService);
            }
        }
    
        REPORT_1("name", "filename"),
        REPORT_2("name", "filename"),
        ...
    }
    
  3. ==============================

    3.열거 형이 인스턴스화 될 때 스프링 컨테이너가 이미 실행 및 실행 중인지 제어하기가 어려울 것입니다 (테스트 케이스에이 유형의 변수가있는 경우 컨테이너가 일반적으로 없을 것이며, 거기 도움을). 난 그냥 dataprepare - 서비스 또는 뭔가 당신에게 enum - 매개 변수와 조회 방법과 특정 params 줄 것을 권하고 싶습니다.

    열거 형이 인스턴스화 될 때 스프링 컨테이너가 이미 실행 및 실행 중인지 제어하기가 어려울 것입니다 (테스트 케이스에이 유형의 변수가있는 경우 컨테이너가 일반적으로 없을 것이며, 거기 도움을). 난 그냥 dataprepare - 서비스 또는 뭔가 당신에게 enum - 매개 변수와 조회 방법과 특정 params 줄 것을 권하고 싶습니다.

  4. ==============================

    4.탐구하고 싶은 또 다른 접근 방식이 있습니다. 그러나 빈을 enum에 주입하는 대신 빈을 enum과 연관시킵니다

    탐구하고 싶은 또 다른 접근 방식이 있습니다. 그러나 빈을 enum에 주입하는 대신 빈을 enum과 연관시킵니다

    열거 형 WidgetType 및 Widget 클래스가 있다고 가정 해 보겠습니다.

    public enum WidgetType {
      FOO, BAR;
    }
    
    public class Widget {
    
      WidgetType widgetType;
      String message;
    
      public Widget(WidgetType widgetType, String message) {
        this.widgetType = widgetType;
        this.message = message;
      }
    }
    

    Factory BarFactory 또는 FooFactory를 사용하여이 유형의 위젯을 만들고 싶습니다.

    public interface AbstractWidgetFactory {
      Widget createWidget();
      WidgetType factoryFor();
    }
    
    @Component
    public class BarFactory implements AbstractWidgetFactory {
      @Override
      public Widget createWidget() {
        return new Widget(BAR, "A Foo Widget");
      }
      @Override
      public WidgetType factoryFor() {
        return BAR;
      }
    }
    
    @Component
    public class FooFactory implements AbstractWidgetFactory {
      @Override
      public Widget createWidget() {
        return new Widget(FOO, "A Foo Widget");
      }
      @Override
      public WidgetType factoryFor() {
        return FOO;
      }
    }
    

    WidgetService는 대부분의 작업이 이루어지는 곳입니다. 여기에는 등록 된 모든 WidgetFactories의 트랙을 유지하는 간단한 AutoWired 필드가 있습니다. postConstruct 조작으로서, enum 맵과 관련 팩토리를 작성합니다.

    이제 클라이언트는 WidgetService 클래스를 삽입하고 지정된 enum 유형에 대한 팩토리를 가져올 수 있습니다.

    @Service
    public class WidgetService {
    
      @Autowired
      List<AbstractWidgetFactory> widgetFactories;
    
      Map<WidgetType, AbstractWidgetFactory> factoryMap = new HashMap<>();
    
      @PostConstruct
      public void init() {
        widgetFactories.forEach(w -> {
          factoryMap.put(w.factoryFor(), w);
        });
      }
    
      public Widget getWidgetOfType(WidgetType widgetType) {
        return factoryMap.get(widgetType).createWidget();
      }
    
    }
    
  5. ==============================

    5.열거 형은 정적이므로 정적 컨텍스트에서 Bean에 액세스하는 방법을 찾아야합니다.

    열거 형은 정적이므로 정적 컨텍스트에서 Bean에 액세스하는 방법을 찾아야합니다.

    ApplicationContextAware 인터페이스를 구현하는 ApplicationContextProvider라는 클래스를 생성 할 수 있습니다.

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class ApplicationContextProvider implements ApplicationContextAware{
    
     private static ApplicationContext appContext = null;
    
     public static ApplicationContext getApplicationContext() {
       return appContext;
     }
    
     public void setApplicationContext(ApplicationContext appContext) throws BeansException {
       this.appContext = appContext;
     }
    }
    

    다음과 같이 응용 프로그램 컨텍스트 파일을 추가하십시오.

    <bean id="applicationContextProvider" class="xxx.xxx.ApplicationContextProvider"></bean>
    

    그 후에는 다음과 같이 정적 인 방법으로 응용 프로그램 컨텍스트에 액세스 할 수 있습니다.

    ApplicationContext appContext = ApplicationContextProvider.getApplicationContext();
    
  6. ==============================

    6.이게 니가 필요한 것 같아.

    이게 니가 필요한 것 같아.

    public enum MyEnum {
        ONE,TWO,THREE;
    }
    

    평소와 같이 enum을 Autowire

    @Configurable
    public class MySpringConfiguredClass {
    
              @Autowired
          @Qualifier("mine")
              private MyEnum myEnum;
    
    }
    

    여기에 트릭이 있는데, factory-method = "valueOf"를 사용하고 lazy-init = "false"

    그래서 컨테이너는 빈을 선행으로 만듭니다.

    <bean id="mine" class="foo.bar.MyEnum" factory-method="valueOf" lazy-init="false">
        <constructor-arg value="ONE" />
    </bean>
    

    그리고 너 끝났어!

  7. ==============================

    7.어쩌면이 솔루션을 사용할 수 있습니다.

    어쩌면이 솔루션을 사용할 수 있습니다.

    public enum ChartTypes {
    AREA_CHART("Area Chart", XYAreaChart.class),
    BAR_CHART("Bar Chart", XYBarChart.class),
    
    private String name;
    private String serviceName;
    
    ChartTypes(String name, Class clazz) {
        this.name = name;
        this.serviceName = clazz.getSimpleName();
    }
    
    public String getServiceName() {
        return serviceName;
    }
    
    @Override
    public String toString() {
        return name;
    }
    }
    

    그리고 열거 형 콩이 필요한 다른 클래스에서 :

    ChartTypes plotType = ChartTypes.AreaChart
    Object areaChartService = applicationContext.getBean(chartType.getServiceName());
    
  8. ==============================

    8.수동으로 메소드에 전달하십시오.

    수동으로 메소드에 전달하십시오.

    public enum ReportType {
    
        REPORT_1("name", "filename"),
        REPORT_2("name", "filename"),
        REPORT_3("name", "filename")
    
        public abstract Map<String, Object> getSpecificParams();
    
        public Map<String, Object> getCommonParams(DataPrepareService  dataPrepareService){
            // some code that requires service
        }
    }
    

    관리 Bean에서만 메소드를 호출하면이 빈에 메소드를 삽입하고 각 호출에서 enum에 대한 참조를 전달할 수 있습니다.

  9. from https://stackoverflow.com/questions/16318454/inject-bean-into-enum by cc-by-sa and MIT license