レポート用のデータを準備する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;
、しかしうまくいきませんでした
私のサービスをenumに注入するにはどうすればよいですか?
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);
}
}
[...]
}
weekens 'answer 内部クラスをstaticに変更すると、春が見えるようになります
たぶんこのようなもの:
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
に挿入する代わりに、bean
を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;
}
}
そして、ファクトリWidget
またはBarFactory
を使用して、このタイプのFooFactory
sを作成したい
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
iesを追跡する簡単なWidgetFactor
フィールドがあります。 postConstruct
操作として、enumおよび関連するファクトリーのマップを作成します。
クライアントはWidgetService
クラスを挿入し、指定された列挙型のファクトリーを取得できるようになりました
@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();
}
}
enumがインスタンス化される時点で、スプリングコンテナーが既に起動して実行されていることを制御するのは困難です(テストケースでこのタイプの変数があった場合、通常、コンテナーは存在しません。そこに役立つ)。 dataprepare-serviceか、enum-parameterを含むlookup-methodを使用してspecific-paramsを提供することをお勧めします。
たぶん、このソリューションを使用できます。
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のBeanが必要な別のクラスで:
ChartTypes plotType = ChartTypes.AreaChart
Object areaChartService = applicationContext.getBean(chartType.getServiceName());
Enum
sは静的なので、静的コンテキストからBeanにアクセスする方法を理解する必要があります。
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();
これはあなたが必要なものだと思う
public enum MyEnum {
ONE,TWO,THREE;
}
通常どおり列挙を自動配線します
@Configurable
public class MySpringConfiguredClass {
@Autowired
@Qualifier("mine")
private MyEnum myEnum;
}
ここにトリックがあります。factory-method= "valueOf"を使用し、lazy-init = "false"を確認してください。
コンテナはBeanを前もって作成します
<bean id="mine" class="foo.bar.MyEnum" factory-method="valueOf" lazy-init="false">
<constructor-arg value="ONE" />
</bean>
これで完了です!