我有DataPrepareService为报告准备数据,我有一个包含报告类型的枚举,我需要将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;
,但它不起作用
如何将我的服务注入枚举?
答案 0 :(得分:54)
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如果您将内部类更改为静态,那么Spring可以看到它
答案 1 :(得分:10)
也许是这样的:
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"),
...
}
答案 2 :(得分:2)
您可能想探索另一种方法。但是,不是将bean
注入enum
而是将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;
}
}
您想使用Factory Widget
或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
是完成大部分工作的地方。在这里,我有一个简单的AutoWired
字段,该字段跟踪所有已注册的WidgetFactor
ies。作为postConstruct
操作,我们创建了枚举和关联工厂的映射。
现在,客户可以注入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();
}
}
答案 3 :(得分:1)
在枚举实例化时,很难控制弹簧容器已经启动并运行(如果在测试用例中有这种类型的变量,你的容器通常不会在那里,甚至是facej自动装配不会有帮助)。我建议让dataprepare-service或者某些东西给你带有enum-parameter查找方法的特定参数。
答案 4 :(得分:0)
Enum
是静态的,因此您必须找到一种从静态上下文访问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();
答案 5 :(得分:0)
我认为这就是你所需要的
public enum MyEnum {
ONE,TWO,THREE;
}
按照惯例自动加载枚举
@Configurable
public class MySpringConfiguredClass {
@Autowired
@Qualifier("mine")
private MyEnum myEnum;
}
这是技巧,使用factory-method =&#34; valueOf&#34;并确保 懒惰-INIT =&#34;假&#34;
所以容器先创建bean
<bean id="mine" class="foo.bar.MyEnum" factory-method="valueOf" lazy-init="false">
<constructor-arg value="ONE" />
</bean>
你完成了!
答案 6 :(得分:0)
也许您可以使用此解决方案;
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());
答案 7 :(得分:-1)
只需手动将其传递给方法
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调用该方法,就可以将其注入这些bean中,并在每次调用时将引用传递给枚举。