我有一个实现接口的服务。现在,我想编写一个映射器,基本上就是说,当我传入此枚举类型时,请使用该服务。这就是我所拥有的
@Service
MyService implements Service {}
@Component
@RequiredArgsConstructor
MyMapper implements Mapper<Enum, Service> {
private final MyService myService;
private ImmutableMap<Enum, Service> MAPPER = ImmutableMap.<MyEnum, MyService>builder()
.put(Enum.A, myService)
.build();;
@Override
public Service map(Enum input) {
return MAPPER.get(input);
}
}
但是,这似乎不起作用。我认为我不允许使用(自动装配的)实例变量来实例化另一个实例变量。
为了解决这个问题,我现在使用单例模式。
@Service
MyService implements Service {}
@Component
@RequiredArgsConstructor
MyMapper implements Mapper<Enum, Service> {
private final MyService myService;
private ImmutableMap<Enum, Service> MAPPER = null;
@Override
public Service map(Enum input) {
if(MAPPER == null){
MAPPER = createMapper();
}
return MAPPER.get(input);
}
private ImmutableMap<Enum, Service> createMapper(){
return ImmutableMap.<MyEnum, MyService>builder()
.put(Enum.A, myService)
.build();;
}
}
这似乎可行,但是我想知道是否还有其他解决方案。
答案 0 :(得分:1)
您正在遇到有关最终变量的极端情况;即使已将其标记为final,该映射的初始化程序语句也会在实例初始化程序块(否则会很有用)之前运行,而该实例初始化程序块将在为变量赋值的构造函数主体之前运行。
我不确定为什么要创建一个仅包含单例值的映射,但是您需要在构造函数体内分配该映射。如果您出于某些原因确实想要此设置,我的建议是:
private final Map<Enum, Service> MAPPER;
public MyMapper(MyService myService) {
MAPPER = Map.of(Enum.A, myService);
}
答案 1 :(得分:1)
最适合此问题的服务定位器。
我的枚举:-
public enum MyEnum {
A,
B
}
创建服务并使用名称“ A”和“ B”(您的枚举的名称为字符串):-
@Service("A")
MyService1 implements Service {}
@Service("B")
MyService2 implements Service {}
创建MyMapper界面:-
public interface MyMapper {
Service map(MyEnum myEnum);
}
配置ServiceLocatorFactoryBean:-
@Bean
public ServiceLocatorFactoryBean serviceLocatorFactoryBean(){
ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
bean.setServiceLocatorInterface(MyMapper.class);
return bean;
}
开始使用:-
@Autowired
MyMapper mapper;