2013-03-13 2 views
4

У меня возникли трудности с пониманием того, почему что-то весной Java Config с использованием @Autowired не работает.Spring Java Config using Autowired вызванный NPE

Во-первых, я пытаюсь переместить все мои аннотации @Autowired в классы Java Config. Это приводит к тому, что мои «POJO» возвращаются в реальные POJO. Затем я могу не только легко их тестировать вне контекста Spring, но и легко и легко использовать макетные объекты.

Так я впервые попробовал это:

@Configuration 
public class Module3ConfigClass { 

    @Autowired 
    private Module1Bean1 module1Bean1; 

    @Autowired 
    private Module2Bean1 module2Bean1; 

    @Bean 
    public Module3Bean1 module3Bean1() { 
     return new Module3Bean1(module1Bean1, module2Bean1); 
    } 
} 

Однако, когда Module3Bean1 конструктор вызывается, как принятый в Beans являются недействительными. Если вы не выполнили вышеприведенное соглашение об именах, оба этих компонента будут созданы отдельным конфигурационным файлом конфигурации Java. Также обратите внимание, что все правильно подключено - я знаю это, потому что все работает отлично, когда теги @Autowired находятся на соответствующих частных полях членов внутри Module3Bean1.

FWIW, я попытался добавить аннотацию @DependsOn к методу module3Bean1(), но имел те же результаты. Думаю, мне просто хотелось бы понять это поведение, правильно ли (я подозреваю, что это так, но почему)?

Наконец, я нашел приемлемый обходной путь, показанный здесь:

@Configuration 
public class Module3ConfigClass { 

    @Bean 
    @Autowired 
    public Module3Bean1 module3Bean1(Module1Bean1 module1Bean1, Module2Bean1 module2Bean1) { 
     return new Module3Bean1(module1Bean1, module2Bean1); 
    } 
} 

Это, кажется, хорошо для меня, но если кто-то захочет это прокомментировать, что будет приветствоваться, а также.

+3

Бобы должны быть созданы до того, как они будут автоуведомлены. Покажите нам, где эти бобы, другая конфигурация. Вам, вероятно, понадобится '@ Import', что' @ Configuration'. –

+1

Хорошо, что они правильно установлены в двух случаях, описанных выше. Во-первых, когда аутсорсинг находится за пределами заводского (конфигурирования) процесса, а второй - когда они автообновлены в показанном коде. Поэтому просто предположите, что это тривиальные бобы каждый в своем собственном (at) Configuration аннотированном классе и импортированы правильно. Мне просто интересно, почему некоторые (at) Autowired beans отображаются в классе конфигурации (at), а некоторые (как показано выше) этого не делают. – JoeG

+0

Тогда я могу только предположить, что все бобы создаются до того, как они станут пригодными для инъекций/автоувеличивания. Что касается вашего обходного пути, я думаю, что метод может быть вызван дважды, один раз для создания '@ Bean' и один раз для' @ Autowired'. Проверьте свои журналы. –

ответ

1

Я думаю, вы столкнулись с той же проблемой, что и я. В моем случае проблема была недопустимой xml-конфигурацией. В моем модуле B я имел конфигурации, как:

<beans> 
     <context:component-scan base-package="com.moduleB"/> 
     <import resource="classpath:applicationContext-moduleA.xml"/> 
</beans> 

В контексте ModuleA я поместил «контекст: аннотация-конфигурация» аннотацию. При изменении импорта/контекста порядок:

<beans> 
     <import resource="classpath:applicationContext-moduleA.xml"/> 
     <context:component-scan base-package="com.moduleB"/> 
</beans> 

для автоматического связывания свойств класса конфигурации начал работать.

+0

Извините, я пропустил этот ответ, когда! Это отличная информация для других, но поскольку у меня не было конфигурации XML и была чистой Java Config, это не отвечает на вопрос (просто говорю вам, почему я не могу принять это как ответ на вопрос!) – JoeG

0

У нас была такая же проблема, и пришел к выводу, что ошибка возникла из-за того, что у нас была круговая зависимость, в которой участвовал BeanPostProcessor.

  • PropertyPlaceholderConfigurer (а BeanPostProcessor) сконфигурирован, чтобы установить его свойство propertiesArray с помощью другого боба:

    <bean id="globalPropertyPlaceholderConfigurer" 
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" 
        lazy-init="false" depends-on="javaLoggingConfigurer"> 
        <property name="locations"> 
         <list> 
          <value>classpath:config/host/${env.instance}.properties</value> 
          <value>WEB-INF/config/host/${env.instance}.properties</value> 
         </list> 
        </property> 
        <property name="ignoreResourceNotFound" value="true" /> 
        <property name="propertiesArray" value="#{springPropertyFinder.findProperties()}" /> 
    </bean> 
    
  • Используемый springPropertyFinder бобов, чтобы установить propertiesArray является не BeanPostProcessor но «нормальный» компонент, который собирает все экземпляры свойств с:

    public Properties[] findProperties() { 
        Map<String, Properties> propertiesMap = applicationContext.getBeansOfType(Properties.class); 
    
        for (String title : propertiesMap.keySet()) { 
         PropertiesLoggerUtil.logPropertiesContent(logger, "Springcontext Properties ("+title+")", propertiesMap.get(title)); 
        } 
    
        return propertiesMap.values().toArray(new Properties[propertiesMap.size()]); 
    } 
    
  • Класс @Configuration содержит компонент из свойств типа

Итак, наше предположение о том, что класс @Configuration был создан без обработки в ConfigurationClassPostProcessor (также BeanPostProcessor), потому что PropertyPlaceholderConfigurer зависит от springPropertyFinder, который зависит от компонента свойств в классе @Configuration. В этих обстоятельствах порядок BeanPostProcessors, вероятно, не настроен.

Эта описанная настройка работает в формате XML, но не с конфигурацией Java.

+1

Это похоже очень похоже - @Autowired также является этапом последующей обработки. В течение месяцев, прошедших с этого поста, мы также смогли подтвердить (или, по нашему мнению, так), что это круговая справочная проблема. Я подозреваю (хотя и не имея доказательств), что, поскольку Autowired был поддержан задолго до (2.5, я думаю), Java Config (3.x) появился вокруг, есть тонкая проблема, похожая на наборы вложенных классов конфигурации. – JoeG