Использование параметра autowired в другой переменной экземпляра - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть сервис, который реализует интерфейс. Теперь я хочу написать картограф, который в основном говорит, что когда я передаю этот тип enum, использую этот сервис. Это то, что у меня есть

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

Однако, похоже, это не работает. Я думаю, что мне не разрешено использовать переменную экземпляра (autowired) для создания экземпляра другой переменной экземпляра.

Чтобы решить эту проблему, я теперь использовал шаблон синглтона.

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

Кажется, это работает, но мне было интересно, есть ли другие варианты решения этой проблемы.

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Для этой задачи лучше всего подойдет сервисный локатор.

Мой Enum: -

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;
0 голосов
/ 08 ноября 2018

Вы столкнулись с крайним случаем в отношении конечных переменных даже если он помечен как финальный, оператор инициализатора карты выполняется перед блоками инициализатора экземпляра (что в противном случае было бы полезно), которые выполняются перед телом конструктора, который присваивает значение переменной.

Я не уверен, почему вы хотите создать карту только для хранения одноэлементного значения, но вам нужно будет назначить карту внутри тела вашего конструктора. Если вы действительно хотите эту настройку по какой-либо причине, я бы предложил сделать следующее:

private final Map<Enum, Service> MAPPER;

public MyMapper(MyService myService) {
    MAPPER = Map.of(Enum.A, myService);
}
...