programing

열거형에 콩 주입

css3 2023. 11. 1. 22:33

열거형에 콩 주입

보고서를 위한 데이터를 준비하는 DataPrepareService가 있고 보고서 유형을 가진 Enum이 있으며 Enum에 ReportService를 주입하거나 Enum에서 ReportService에 액세스할 수 있어야 합니다.

나의 봉사합니다.

@Service
public class DataPrepareService {
    // my service
}

나의 열거:

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;

,하지만 그것은 작동하지 않았다.

서비스를 열거형에 주입하려면 어떻게 해야 합니까?

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

[...]

}

weeknes의 답변은 봄이 볼 수 있도록 내부 클래스를 정적으로 바꾸면 효과가 있습니다.

아마 이런 거겠지.

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"),
    ...
}

여러분이 탐색하고 싶은 또 다른 접근 방법이 있습니다.하지만 주사를 놓는 대신에bean안으로enum그것은 a와 관련이 있습니다.bean의 소리와 함께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;
  }
}

그리고 당신이 만들고 싶은 것은Widget공장을 사용하는 이 유형의 sBarFactory아니면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대부분의 작업이 이루어지는 곳입니다.여기 간단한 것이 있습니다.AutoWired등록된 모든 정보를 추적하는 필드WidgetFactories. as a.postConstructoperation 우리는 열거와 관련된 공장의 지도를 만듭니다.

이제 고객들은 환자들에게WidgetServiceclass and get factory를 지정된 열거형에 사용합니다.

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

}

Enums는 정적이기 때문에 정적인 맥락에서 콩에 접근할 수 있는 방법을 찾아야 합니다.

이름이 붙은 클래스를 만들 수 있습니다.ApplicationContextProvider를 구현하는ApplicationContextAware인터페이스.

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

열거형이 인스턴스화될 때 스프링 컨테이너가 이미 가동 중이고 실행 중이라는 것을 제어하는 것은 어렵습니다(테스트 케이스에 이 유형의 변수가 있는 경우 컨테이너는 일반적으로 존재하지 않습니다. aspectj autowireing이 여기에 도움이 되지 않음).저는 그냥 데이터 준비 서비스 같은 것이 enum-parameter가 있는 lookup-parameter와 함께 특정 method를 제공하도록 하는 것을 추천합니다.

당신에게 필요한 것은 이것이라고 생각합니다.

public enum MyEnum {
    ONE,TWO,THREE;
}

일반적으로 열거형 자동 배선

@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>

그리고 당신은 끝!

수동으로 메소드에 전달하기만 하면 됩니다.

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
    }
}

관리된 콩에서만 방법을 호출하는 한, 이 콩들에 주입하고 각 호출의 열거에 대한 참조를 전달할 수 있습니다.

이 솔루션을 사용할 수도 있습니다.

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

그리고 당신이 Enum의 콩을 필요로 하는 다른 클래스에서는:

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

언급URL : https://stackoverflow.com/questions/16318454/inject-bean-into-enum