Как аннотация @Required работает с JavaConfig?

Я довольно новичок в Spring Framework, и у меня есть проблемы, чтобы понять@Required аннотация в сочетании с настроенным приложением Java.

Вот пример.

Config-File

@Configuration
public class AppConfig {
    @Bean
    public Movie movieA() {
        return new Movie();
    }

    @Bean
    public MovieHolder holder() {
        return new MovieHolder();
    }
}

MovieHolder.java

public class MovieHolder {

    private Movie movie;

    public Movie getMovie() {
        return movie;
    }

    @Required
    public void setMovie(Movie movie) {
        this.movie = movie;
    }
}

Инициализация контекста

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MovieHolder holder = (MovieHolder) context.getBean("holder");
System.out.println("movie: " + holder.getMovie());

Насколько я понял документация@Required аннотации, должно возникнуть исключение, потому что фильм неустановить напрямую или с помощью автоматической проводки. Вместо этого есть выход.movie: null

Что я делаю неправильно? Или нетт это правильное использование@Required аннотаций?

Ответы на вопрос(2)

@Bean RequiredAnnotationBeanPostProcessor с переопределениемshouldSkip () метод.

Да, он проверяет мои bean-компоненты, но не работает, даже если я устанавливаю все необходимые свойства, то есть всегда происходит сбой.

Я думаю, что у Spring есть реальная проблема с поддержкой@Необходимые аннотация для Java Config, поскольку Spring не может определить, было ли установлено свойство, когда вы делаете это непосредственно в коде Java. (Оно может'проверитьноль' поля позже, так как это будет означать изменение семантики@Необходимые аннотация, которая должна позволять явно устанавливать нулевые значения).

Когда вы используете конфигурацию XML, Spring создает объект-обертку для установки свойств, чтобы он мог отслеживать все настроенныеSetXXX ()» операции.

Заключение: нет разумного способа включить@Необходимые аннотация для бинов, созданных в [email protected] классы.

(На мой взгляд, очень неприятная особенность, так как автор класса бина и пользователь класса могут быть разными людьми).

Решение Вопроса

которые вы создаете, является вашей собственной ответственностью.BeanPostProcessor который обрабатывает определения компонентов в классах, помеченных@Configuration называетсяConfigurationClassPostProcessor,BeanPostProcessor который обрабатывает ваш@Required по умолчанию аннотацияRequiredAnnotationBeanPostProcessor, который зарегистрирован по умолчанию при использованииcontext:annotation-config а такжеcontext:component-scan в вашей конфигурации. Если вы не используете эти два тега, вы можете даже зарегистрировать свой собственныйRequiredAnnotationBeanPostProcessor как .bean

Теперь реализация по умолчаниюRequiredAnnotationBeanPostProcessor имеет метод, называемыйboolean shouldSkip(..) который проверяет логический атрибут с именемSKIP_REQUIRED_CHECK_ATTRIBUTE, Значение этого атрибута проверяется для каждого компонента во время последующей обработкиRequiredAnnotationBeanPostProcessor, Если он вернетсяfalse,@Required ограничение применяется, в противном случае это не так.

ТеперьConfigurationClassPostProcessor установите значение этого атрибута вtrue при создании определений бина из@Configuration классы (я думаю, по той причине, что есливы определяют боб,вы следует убедиться, что он обладает необходимыми свойствами). Следовательно@Required не применяется для таких бобов.

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

Если вы действительно хотите обеспечить соблюдение@Required ограничения, вам придется переопределитьRequiredAnnotationBeanPostProcessorпереопределитьboolean shouldSkip(..) метод и зарегистрировать этот класс вместо по умолчаниюRequiredAnnotationBeanPostProcessor, И как документация дляRequiredAnnotationBeanPostProcessor говорит:

По умолчанию RequiredAnnotationBeanPostProcessor будет зарегистрирован "Контекст: аннотация-конфигурация» а также "Контекст: компонент сканирования» XML-теги. Удалите или отключите конфигурацию аннотации по умолчанию, если вы намерены указать пользовательское определение компонента RequiredAnnotationBeanPostProcessor.

Другим способом было бы использоватьinitMethod атрибут на вашем@Bean аннотаций. Который может выполнять проверки, чтобы увидеть, что требуемые свойства действительно установлены. Тем не менее, так как это конфигурация на основе кода, вы также можете назвать этоinit метод себя.

Кроме того, по моему мнению, нет смысла проходить через много проблем, чтобы использовать свой собственныйRequiredAnnotationBeanPostProcessor, как сказано в следующей документации:

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

Итак, подведем итог: @Required Безразлично»работать с@Configuration классы по умолчанию. Если вам нужно убедиться, что все ваши свойства установлены, вы также можете сделать это сами, когда создадите компонент в@Bean методы (вызывая некоторыеinit метод, который выполняет такие проверки или просто предоставляя необходимые свойства самостоятельно). И если выдействительно нужно сделать@Required аннотации работы, вымне нужно использовать собственную реализациюRequiredAnnotationBeanPostProcessorзарегистрируйте его как боб в контексте весны и откажитесь от преимуществ.context:annotation-config

 a.ha28 мая 2013 г., 08:59
Ах хорошо. Теперь для меня очевидно, что вы имели в виду. - Спасибо!
 a.ha27 мая 2013 г., 15:43
Ну, спасибо за ваше решение, я попробую. Но я нене понимаю, почему это так сложно? Есть ли причины не использовать@Required-Аннотация при использовании конфигураций, определенных в Java?
 a.ha28 мая 2013 г., 08:54
Дело не в том, что мне обязательно нужно@Required-Тег. Я'Я просто все еще удивляюсь, что этот тег всегда игнорируется, когда используется javabased Configuration. В яConfigurationClassBeanDefinitionReaderнашел следующую строку:beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE); что является причиной, по которой необходимая проверка уже пропущена.
 Bhashit Parikh28 мая 2013 г., 08:57
Да, этоS, что говорит мой ответ. Это не очень удивительно, если учесть, что создание бобов выполняется вами. Это имеет смысл. Если вам нужно что-то гарантировать, просто сделайте это при создании компонента. Отредактировал ответ, хотя, я положил вfalse вместоtrue в одном месте.
 Bhashit Parikh27 мая 2013 г., 15:57
Используйте это, если выочень нужно к. Есть предостережения (теряя преимуществаcontext:annotation-config) и нет особой пользы от его использования в любом случае. Это'не очень сложно, хотя. Официальная документация очень помогает, и если это не такт, вы можете просто просмотреть исходный код. Возможно, вы используете@Required чтобы убедиться, что какое-то свойство имеет допустимое значение и чтоне то, что@Required аннотация делает. Если вам нужно это сделать, просто проверьте это в своем@Bean метод или реализоватьinitMethod как уже упоминалось в ответе.
 Bhashit Parikh28 мая 2013 г., 09:02
Хорошо. Рад, что это помогло.

Ваш ответ на вопрос