Spring Core Annotations

Spring Core Аннотации

1. обзор

Мы можем использовать возможности движка Spring DI, используя аннотации в пакетахorg.springframework.beans.factory.annotation andorg.springframework.context.annotation.

Мы часто называем их «аннотациями ядра Spring» и рассмотрим их в этом руководстве.

2.1. @Autowiredс

Мы можем использовать от@Autowired доmark a dependency which Spring is going to resolve and inject. Мы можем использовать эту аннотацию с помощью конструктора, сеттера или внедрения поля.

Конструктор впрыска:

class Car {
    Engine engine;

    @Autowired
    Car(Engine engine) {
        this.engine = engine;
    }
}

Сеттер впрыска:

class Car {
    Engine engine;

    @Autowired
    void setEngine(Engine engine) {
        this.engine = engine;
    }
}

Полевая инъекция:

class Car {
    @Autowired
    Engine engine;
}

@Autowired имеет аргументboolean с именемrequired со значением по умолчаниюtrue. Он настраивает поведение Spring, когда он не находит подходящий компонент для подключения. Когдаtrue, генерируется исключение, в противном случае ничего не подключено.

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

Начиная с версии 4.3, нам не нужно явно аннотировать конструкторы с помощью@Autowired, если мы не объявляем по крайней мере два конструктора.

Чтобы узнать больше, посетите наши статьи о@Autowired иconstructor injection.

2.2. @Beanс

@Bean отмечает фабричный метод, который создает экземпляр компонента Spring:

@Bean
Engine engine() {
    return new Engine();
}

Spring calls these methods, когда требуется новый экземпляр возвращаемого типа.

Полученный компонент имеет то же имя, что и фабричный метод. Если мы хотим назвать его по-другому, мы можем сделать это с помощью аргументовname илиvalue этой аннотации (аргументvalue является псевдонимом для аргументаname) :

@Bean("engine")
Engine getEngine() {
    return new Engine();
}

Обратите внимание, что все методы, помеченные@Bean, должны быть в классах@Configuration.

2.3. @Qualifierс

Мы используем@Qualifier вместе с@Autowired доprovide the bean id or bean name, которые мы хотим использовать в неоднозначных ситуациях.

Например, следующие два компонента реализуют один и тот же интерфейс:

class Bike implements Vehicle {}

class Car implements Vehicle {}

Если Spring необходимо внедрить bean-компонентVehicle, он получит несколько подходящих определений. В таких случаях мы можем указать имя bean-компонента явно, используя аннотацию@Qualifier.

Использование инжектора конструктора:

@Autowired
Biker(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}

Используя сеттерную инъекцию:

@Autowired
void setVehicle(@Qualifier("bike") Vehicle vehicle) {
    this.vehicle = vehicle;
}

В качестве альтернативы:

@Autowired
@Qualifier("bike")
void setVehicle(Vehicle vehicle) {
    this.vehicle = vehicle;
}

Используя полевую инъекцию:

@Autowired
@Qualifier("bike")
Vehicle vehicle;

Для более подробного описания прочтитеthis article.

2.4. @Requiredс

@Required в методах установки, чтобы отметить зависимости, которые мы хотим заполнить через XML:

@Required
void setColor(String color) {
    this.color = color;
}

    

В противном случае будет выброшеноBeanInitializationException.

2.5. @Valueс

Мы можем использовать@Value для внедрения значений свойств в bean-компоненты. Он совместим с конструктором, установщиком и внедрением поля.

Конструктор впрыска:

Engine(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

Сеттер впрыска:

@Autowired
void setCylinderCount(@Value("8") int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

В качестве альтернативы:

@Value("8")
void setCylinderCount(int cylinderCount) {
    this.cylinderCount = cylinderCount;
}

Полевая инъекция:

@Value("8")
int cylinderCount;

Конечно, ввод статических значений бесполезен. Следовательно, мы можем использоватьplaceholder strings в@Value для привязки значенийdefined in external sources, например, в файлах.properties или.yaml.

Предположим, следующий файл.properties:

engine.fuelType=petrol

Мы можем ввести значениеengine.fuelType следующим образом:

@Value("${engine.fuelType}")
String fuelType;

Мы можем использовать@Value даже со SpEL. Более сложные примеры можно найти в нашемarticle about @Value.

2.6. @DependsOnс

Мы можем использовать эту аннотацию, чтобы сделать Springinitialize other beans before the annotated one. Обычно это поведение автоматическое, основанное на явных зависимостях между компонентами.

Нам нужна только эта аннотацияwhen the dependencies are implicit, например, загрузка драйвера JDBC или инициализация статической переменной.

Мы можем использовать@DependsOn для зависимого класса, указав имена зависимых bean-компонентов. Аргументу аннотацииvalue нужен массив, содержащий имена bean-компонентов зависимости:

@DependsOn("engine")
class Car implements Vehicle {}

В качестве альтернативы, если мы определяем bean-компонент с аннотацией@Bean, фабричный метод должен быть аннотирован@DependsOn:

@Bean
@DependsOn("fuel")
Engine engine() {
    return new Engine();
}

2.7. @Lazyс

Мы используем@Lazy, когда хотим лениво инициализировать наш bean-компонент. По умолчанию Spring с готовностью создает все одноэлементные компоненты при запуске / начальной загрузке контекста приложения.

Однако бывают случаи, когдаwe need to create a bean when we request it, not at application startup.

Эта аннотация ведет себя по-разному в зависимости от того, где мы ее точно разместили. Мы можем надеть это:

  • аннотированный метод фабрики bean-компонентов@Bean, чтобы отложить вызов метода (отсюда и создание bean-компонента)

  • класс @Configuration и все содержащиеся в нем методы@Bean будут затронуты

  • класс@Component, который не является классом@Configuration, этот bean-компонент будет инициализирован лениво

  • конструктор, установщик или поле@Autowired для ленивой загрузки самой зависимости (через прокси)

Эта аннотация имеет аргумент с именемvalue со значением по умолчаниюtrue. Полезно переопределить поведение по умолчанию.

Например, маркировка bean-компонентов для быстрой загрузки, когда глобальная настройка является ленивой, или настройка определенных методов@Bean для активной загрузки в классе@Configuration, помеченном@Lazy:

@Configuration
@Lazy
class VehicleFactoryConfig {

    @Bean
    @Lazy(false)
    Engine engine() {
        return new Engine();
    }
}

Для дальнейшего чтения посетитеthis article.

2.8. @Lookupс

Метод, помеченный@Lookup, сообщает Spring, что нужно вернуть экземпляр типа возвращаемого метода, когда мы его вызываем.

Подробная информация об аннотацииcan be found in this article.

2.9. @Primaryс

Иногда нам нужно определить несколько бинов одного типа. В этих случаях инъекция будет неудачной, потому что Spring не имеет ни малейшего понятия, какой бин нам нужен.

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

Однако, в большинстве случаев нам нужен конкретный компонент, а редко - другие. Мы можем использовать@Primary, чтобы упростить этот случай: еслиwe mark the most frequently used bean with @Primary будет выбран в неквалифицированных точках инъекции:

@Component
@Primary
class Car implements Vehicle {}

@Component
class Bike implements Vehicle {}

@Component
class Driver {
    @Autowired
    Vehicle vehicle;
}

@Component
class Biker {
    @Autowired
    @Qualifier("bike")
    Vehicle vehicle;
}

В предыдущем примереCar - это основное транспортное средство. Следовательно, в классеDriver Spring внедряет bean-компонентCar. Конечно, в bean-компонентеBiker значение поляvehicle будет объектомBike, поскольку оно квалифицировано.

2.10. @Scopeс

Мы используем@Scope для определенияscope класса@Component или определения@Bean.. Это может бытьsingleton, prototype, request, session, globalSession или некоторая настраиваемая область.

Например:

@Component
@Scope("prototype")
class Engine {}

3. Контекстные аннотации

Мы можем настроить контекст приложения с помощью аннотаций, описанных в этом разделе.

3.1. @Profileс

Если мы хотим, чтобы Spring былuse a @Component class or a @Bean method only when a specific profile is active, мы можем отметить его@Profile. Мы можем настроить имя профиля с помощью аргумента аннотацииvalue:

@Component
@Profile("sportDay")
class Bike implements Vehicle {}

Вы можете узнать больше о профилях вthis article.

3.2. @Importс

Мы можем использоватьspecific @Configuration classes without component scanning с этой аннотацией. Мы можем предоставить этим классам аргумент@Import ’svalue:

@Import(VehiclePartSupplier.class)
class VehicleFactoryConfig {}

3.3. @ImportResourceс

Мы можемimport XML configurations с этой аннотацией. Мы можем указать расположение XML-файла с помощью аргументаlocations или его псевдонима, аргументаvalue:

@Configuration
@ImportResource("classpath:/annotations.xml")
class VehicleFactoryConfig {}

3.4. @PropertySourceс

С помощью этой аннотации мы можемdefine property files for application settings:

@Configuration
@PropertySource("classpath:/annotations.properties")
class VehicleFactoryConfig {}

@PropertySource использует функцию повторяющихся аннотаций Java 8, что означает, что мы можем пометить класс с ее помощью несколько раз:

@Configuration
@PropertySource("classpath:/annotations.properties")
@PropertySource("classpath:/vehicle-factory.properties")
class VehicleFactoryConfig {}

3.5. @PropertySourcesс

Мы можем использовать эту аннотацию, чтобы указать несколько конфигураций@PropertySource:

@Configuration
@PropertySources({
    @PropertySource("classpath:/annotations.properties"),
    @PropertySource("classpath:/vehicle-factory.properties")
})
class VehicleFactoryConfig {}

Обратите внимание, что начиная с Java 8 мы можем достичь того же с помощью функции повторяющихся аннотаций, как описано выше.

4. Заключение

В этой статье мы рассмотрели наиболее распространенные аннотации ядра Spring. Мы увидели, как настроить проводку bean-компонента и контекст приложения, а также как маркировать классы для сканирования компонентов.

Как обычно доступны примерыover on GitHub.