Справочное руководство Spring 5: Конфигурация контейнера на основе аннотаций

Spring Boot Java Spring

Эта статья участвовала в третьем этапе курса «High Yield Update» тренировочного лагеря для создателей Nuggets. Подробнее см.:Dig Li Project | Идет третий этап тренировочного лагеря создателя, «написание» личного влияния.

Конфигурацию контейнера Spring можно выполнить двумя способами: один на основе XML-файлов, а другой — на основе аннотаций. Внедрение аннотации выполняется перед внедрением XML. Поэтому, когда оба используются одновременно, конфигурация XML переопределяет свойства, введенные аннотацией.

В этой статье в основном будут представлены аннотации @Required, @Autowired, @PostConstruct, @PreDestroy и @Resource.

Эти аннотацииcontext:annotation-config/представлять. По сути, введение этой конфигурации будет неявно регистрировать AutoWiredAnnotationBeanPostProcessor (предоставляя @Autowired), CommonAnnotationBeanPostProcessor (предоставляя @PostConstruct, @PreDestroy, @Resource), RequiredAnnotationBeanPostProcessor (предоставляя @Required), тем самым обеспечивая функции каждой аннотации.

Ниже мы представим функции каждой аннотации отдельно.

@Required

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

Однако, начиная с Spring Framework 5.1, аннотация @Required официально устарела в пользу использования внедрения конструктора для необходимых свойств или использования пользовательской реализации InitializingBean.afterPropertiesSet() и методов установки свойств bean-компонента.

Пример кода выглядит следующим образом:

public class RequiredBean {

    private BeanA  beanA;

    @Required
    public void setBeanA(BeanA beanA){
        this.beanA=beanA;

    }
}

@Autowired

@Autowired автоматически вставляет необходимые поля, параметры и т. д. Аннотация @Inject JSR 330 может заменить аннотацию Spring @Autowired.

Вы можете аннотировать конструктор с помощью @Autowired следующим образом:

public class AutowiredBean {

    private BeanA beanA;

    @Autowired
    public AutowiredBean(BeanA beanA){
        this.beanA=beanA;
    }
}

Начиная с Spring Framework 4.3, если целевой компонент определяет только один конструктор, больше нет необходимости использовать аннотацию @Autowired для таких конструкторов. Однако, если доступно несколько конструкторов, по крайней мере один из них должен быть аннотирован, чтобы указать контейнеру, какой из них использовать.

@Autowired также может быть аннотирован для традиционных методов установки, как показано в следующем примере:

public class AutowiredBean {

    private BeanB beanB;

    @Autowired
    public void setBeanB(BeanB beanB){
        this.beanB=beanB;
    }
}

Также можно применять аннотации к любому имени и нескольким параметрам следующим образом:

    @Autowired
    public void configAB(BeanA beanA , BeanB beanB){
        this.beanA=beanA;
        this.beanB=beanB;
        
    }

@Autowired также можно использовать в таких полях:

    @Autowired
    private BeanC beanC;

Вы также можете получить все bean-компоненты этого конкретного типа из ApplicationContext, добавив аннотации к полям или методам, которым требуется массив этого типа, как показано в следующем примере:

    @Autowired
    private BeanC[] beanCList;

Если вы хотите, чтобы элементы в массиве или списке были упорядочены в определенном порядке, целевой компонент может реализовать интерфейс org.springframework.core.Ordered, или вы можете использовать аннотации @Order или стандартные @Priority. В противном случае их порядок соответствует порядку регистрации, определенному соответствующим целевым компонентом в контейнере.

Экземпляры карты также могут быть внедрены, если ключ имеет тип String. Значение Map включает в себя все bean-компоненты, типы которых совпадают, а ключи — это имя bean-компонента. Следующее:

    @Autowired
    public void configMapA(Map<String,BeanA> mapA){
    this.mapA=mapA;
    }

@Autowired имеет обязательный атрибут, если bean-компонент для внедрения может не существовать, он может быть следующим:

    @Autowired(required = false)
    public void setBeanC(BeanC beanC){
    }

Рекомендуется использовать атрибут «required» @Autowired вместо использования аннотации @Required в методе установки. Атрибут «обязательный» указывает, что атрибут необходим для автозагрузки, и если он не может быть загружен автоматически, этот атрибут игнорируется. Для @Required, если значение не определено, будет сообщено об исключении.

Необязательные свойства определенных зависимостей также могут быть выражены через java.util.Optional в Java 8, как показано в следующем примере:

    @Autowired
    public void setMovieFinder(Optional<BeanC> BeanC) {
    }

В Spring Framework 5.0 вы также можете использовать аннотацию @Nullable:

    @Autowired
    public void setMovieFinderC(@Nullable BeanC beanC) {
    }

Spring может использовать @Autowired для автоматического разрешения некоторых bean-компонентов по умолчанию, таких как: BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher и MessageSource. Эти интерфейсы и их интерфейсы расширения (например, ConfigurableApplicationContext или ResourcePatternResolver). ApplicationContext автоматически внедряется следующим образом:

    @Autowired
    private ApplicationContext context;

Примечание. Аннотации @Autowired, @Inject, @Value и @Resource обрабатываются в Spring BeanPostProcessor, что означает, что вы не можете использовать эти аннотации в своих собственных типах BeanPostProcessor, BeanFactoryPostProcessor.

@primary

При внедрении по типу может быть несколько кандидатов, и предпочтительный объект может быть представлен аннотацией @Primary. Следующее:

@Configuration
public class ConfigBean {

    @Bean
    @Primary
    public BeanA firstBeanA() { return new BeanA(); }

    @Bean
    public BeanA secondBeanA() {  return new BeanA();}

}

@Qualifier

@Primary — это эффективный способ использовать автозагрузку по типу в нескольких экземплярах, но если вам нужен более детальный контроль над внедряемыми bean-компонентами, вы можете использовать @Qualifier. Следующее:

    @Bean
    @Qualifier("main")
    public BeanC beanC() {  return new BeanC();}
    @Autowired
    @Qualifier("main")
    private BeanA beanA;

    @Autowired
    public void setBeanA(@Qualifier("main") BeanA beanA){

    }

Значение квалификатора не уникально, это просто критерий фильтра.

@Autowired обычно используется для сопоставления по типу, а @Resource — для сопоставления по имени.

Также возможно создание пользовательских аннотаций:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {

        String value();
}

Дженерики

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

public class StringStore implements Store<String> {
}

public class IntegerStore implements Store<Integer> {
}
    @Bean
    public StringStore stringStore() {
        return new StringStore();
    }

    @Bean
    public IntegerStore integerStore() {
        return new IntegerStore();
    }
public class GenericBean {

    @Autowired
    private Store<String> s1; // <String> qualifier, injects the stringStore bean

    @Autowired
    private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean

    // Inject all Store beans as long as they have an <Integer> generic
    // Store<String> beans will not appear in this list
    @Autowired
    private List<Store<Integer>> s;

}

@Resource

@Resource используется в полях или методах установки, по умолчанию @Resource вводится по имени.

public class ResourceBean {
    
    @Resource(name = "beanA")
    private BeanA BeanA;
}

Если имя не указано явно, имя по умолчанию получается из имени поля или метода установки.

При использовании @Resource, если явное имя не указано и аналогично @Autowired, @Resource находит совпадение основного типа вместо указанного bean-компонента и разрешает известные разрешимые зависимости: BeanFactory, ApplicationContext, ResourceLoader, ApplicationEventPublisher и интерфейс MessageSource.

@PostConstruct и @PreDestroy

Эти две аннотации в основном используются в качестве обратных вызовов жизненного цикла. Следующее:

public class ConstructBean   {

    @PostConstruct
    public void populateMovieCache() {
        // populates the movie cache upon initialization...
    }

    @PreDestroy
    public void clearMovieCache() {
        // clears the movie cache upon destruction...
    }
}

Как и @Resource, типы аннотаций @PostConstruct и @PreDestroy являются частью стандартной библиотеки Java JDK 6–8. Однако весь пакет javax.annotation был отделен от основных модулей Java в JDK 9 и в конечном итоге удален в JDK 11. Артефакт javax.annotation-api теперь должен быть доступен через maven Central, если это необходимо, просто добавьте его в путь к классам приложения, как и любую другую библиотеку.

Код этой статьи может относиться кannotation-config

Дополнительные руководства см.блог флайдина