Autowire / Inject beans в Enum [дубликат]

Тип, который выводится вашим компилятором до назначения для X, - Integer & CharSequence. Этот тип чувствует странным, потому что Integer является окончательным, но он является вполне допустимым типом в Java. Затем он переключается на Integer, что совершенно нормально.

Существует только одно возможное значение для типа Integer & CharSequence: null. С помощью следующей реализации:

 X getCharSequence() {
    return null;
}

Следующее назначение будет работать:

Integer x = getCharSequence();

Из-за этого возможного значения нет причин, по которым назначение должно быть неправильным, даже если оно очевидно бесполезно. Предупреждение было бы полезно.

Реальная проблема - это API, а не сайт вызова

. На самом деле, я недавно написал блог об этом API-шаблоне API . Вы должны (почти) никогда не разрабатывать общий метод для возврата произвольных типов, потому что вы можете (почти) никогда не гарантировать, что выводимый тип будет доставлен. Исключением являются такие методы, как Collections.emptyList(), в случае которых пустота списка (и стирание родового типа) является причиной того, что любой вывод для будет работать:

public static final  List emptyList() {
    return (List) EMPTY_LIST;
}

42
задан Andrej Soroj 1 May 2013 в 13:52
поделиться

6 ответов

Я думаю, что вам нужно

public enum MyEnum {
    ONE,TWO,THREE;
}

Autowire enum как обычно

@Configurable
public class MySpringConfiguredClass {

          @Autowired
      @Qualifier("mine")
          private MyEnum myEnum;

}

Вот трюк, используйте factory-method = "valueOf" и также убедитесь, что lazy-init = "false"

, поэтому контейнер создает bean upfront

<bean id="mine" class="foo.bar.MyEnum" factory-method="valueOf" lazy-init="false">
    <constructor-arg value="ONE" />
</bean>

, и все готово!

0
ответ дан Ashish Shetkar 17 August 2018 в 14:32
поделиться

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

1
ответ дан cproinger 17 August 2018 в 14:32
поделиться

Enum s являются статическими, поэтому вам нужно выяснить способ доступа к компонентам из статического контекста.

Вы можете создать класс с именем 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();
0
ответ дан Josema 17 August 2018 в 14:32
поделиться
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);
        }
    }

[...]

}

Ответ на выходные работает, если вы меняете внутренний класс на статичный, чтобы весна его видна

44
ответ дан Tobias 17 August 2018 в 14:32
поделиться
  • 1
    Ты спасаешь мой день. Спасибо! – Dmytro Boichenko 30 October 2015 в 19:06
  • 2
    Что-то примечание здесь, вышеприведенный код не будет компилироваться, потому что статический класс определен до констант перечисления. Согласно спецификациям java specum перечислены первые числа перед объявлениями классов. Просто поставьте константы вверх и ваш класс. – prettyvoid 2 October 2017 в 09:04
  • 3
    Не забудьте добавить его в качестве компонента в свой config.xml. – Mahdi 5 June 2018 в 13:31

Просто передайте его методу вручную

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

Пока вы вызываете метод только из управляемых компонентов, вы можете вставлять его в эти компоненты и передавать ссылку на перечисление для каждого вызова.

0
ответ дан Wanja Krah 17 August 2018 в 14:32
поделиться

Возможно, что-то вроде этого:

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"),
    ...
}
9
ответ дан weekens 17 August 2018 в 14:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: