Что такое Spring Bean, как его использовать, его возможности и жизненный цикл

Привет, народ! Сегодня я хочу подробно изучить Spring Beans: что такое bean-компонент, как его можно использовать, что такое области видимости и каков жизненный цикл bean-компонента.

Вступление

Компонент является важной концепцией Spring Framework, и поэтому, если вы хотите использовать Spring, важно понимать, что это такое и как работает. По определению bean-компонент Spring - это объект, который составляет основу вашего приложения и управляется контейнером Spring IoC. Компонент - это объект, который создается, собирается и иным образом управляется контейнером Spring IoC. В противном случае bean-компонент - это просто один из многих объектов вашего приложения. Компоненты и зависимости между ними отражаются в метаданных конфигурации, используемых контейнером.

Инверсия управления (IoC)

Внутри Spring компонент использует функцию Инверсия управления, с помощью которой объект определяет свои зависимости, не создавая их. Этот объект делегирует задачу создания и создания экземпляров таких зависимостей контейнеру IoC, облегченному контейнеру Spring.

Например, если у нас есть класс Person , который имеет свойство класса Animal следующим образом:

Предположим, что у Animal есть два свойства: имя и возраст. Чтобы создать экземпляр объекта Person, как правило, мы должны сделать следующее:

Конечно, это можно сделать, но что, если бы мы могли лучше управлять этим видом создания экземпляров? Фактически это означает, что два класса тесно связаны, и если Animal class по какой-то причине изменится (т.е. добавлено свойство), вероятно, изменится и класс Person. И это может стать очень трудным для управления десятками экземпляров Person.

Здесь пригодится Spring и его контейнер, потому что с их помощью объект может извлекать свои зависимости из контейнера IoC, вместо того, чтобы строить зависимости сам по себе. Все, что нам нужно сделать, это предоставить контейнеру соответствующие метаданные конфигурации.

Теперь мы можем сделать следующее:

И создание экземпляра животного с аннотацией bean следующим образом:

Теперь экземпляр Person уже внедрил животное как созданное (с именем Fuffy и возрастом 5). В следующем абзаце мы увидим, как мы можем получить эти bean-компоненты после их создания.

Получить фасоль

По сути, за получение экземпляра компонента из контейнера Spring отвечает метод BeanFactory.getBean (). Обычно вместо BeanFactory мы используем один из известных реализующих классов, как указано в документации здесь. Какую бы реализацию вы ни использовали, существуют (от BeanFactory) разные сигнатуры, с помощью которых мы можем получить bean-компонент из контейнера Spring:

1. По имени: по имени, возвращает объект, если компонент с таким именем существует в контексте приложения, в противном случае генерирует исключение NoSuchBeanDefinitionException.

#by name
Object animal = context.getBean("animal");

2. По имени и типу: по имени и типу возвращает компонент данного типа, если он существует в контексте приложения; это может быть полезно, потому что избегайте приведения возвращаемого объекта. Этот метод может генерировать NoSuchBeanDefinitionException (если такого bean-компонента нет) или BeanNotOfRequiredTypeException (если bean-компонент не требуемого типа)

#by name and type
Animal animal = context.getBean("animal", Animal.class);

3. По типу: он похож на предыдущий, с той разницей, что мы можем найти больше bean-компонентов с тем же типом, созданным; в этом случае мы получим исключение NoUniqueBeanDefinitionException

#by type
Animal animal = context.getBean(Animal.class);

4. По имени с параметрами конструктора: мы можем передать имя компонента и параметры конструктора следующим образом:

#by name and constructor parameters
Animal fuffyAnimal = (Animal) context.getBean("animal", "Fuffy", 5);

В этом случае мы получаем животное по имени Fuffy с возрастом 5 лет. Но если bean-компонент является одноэлементным (то есть не прототипом), мы можем получить BeanDefinitionStoreException.

5. По типу с параметрами конструктора: аналогично предыдущему, но вместо имени мы должны передать тип, и компонент не может быть одноэлементным:

#by type and constructor parameters
Animal fuffyAnimal = (Animal) context.getBean(Animal.class, "Fuffy", 5);

Это основные методы, которые BeanFactory interface дает нам для получения bean-компонентов из контейнера, и обычно мы используем ApplicationContext для вызова этих методов. Более того, чтобы избежать смешивания логики со способом получения bean-компонентов, связанным с фреймворком, мы полагаемся на автоматическое связывание и внедрение зависимостей, чтобы поместить bean-компоненты внутри другого bean-компонента Spring.

Наиболее часто используемые аннотации Spring Bean

Я уже перечислил и подробно обсудил в другой статье наиболее часто используемые аннотации Spring в целом. Здесь я хочу обсудить наиболее распространенные, связанные с фасолью. Все эти аннотации можно найти с помощью функции сканирования компонентов Spring и зарегистрировать как beans в контейнере Spring.

  1. @Component: аннотация уровня класса, которая по умолчанию обозначает компонент с тем же именем, что и имя класса, с первой строчной буквой. Можно указать другое имя, используя аргумент значения аннотации.
  2. @Repository: аннотация уровня класса, представляющая уровень DAO приложения; он обеспечивает автоматическую трансляцию исключений сохраняемости.
  3. @Service: аннотация на уровне класса, представляющая, где обычно находится бизнес-логика, и может вносить изменения в повторное использование кода.
  4. @Controller: аннотация на уровне класса, представляющая контроллеры в Spring MVC (Model-View-Controller). См. Также @RestController для режима REST.
  5. @Configuration: аннотация уровня класса, указывающая, что она может содержать методы определения bean-компонентов, аннотированные с помощью @Bean.

Области действия фасоли

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

1. Синглтон: это означает, что контейнер создает единственный экземпляр этого компонента, и при запросе (по имени или типу) будет возвращен тот же объект.

2. Прототип: каждый раз, когда он запрашивается из контейнера, создается новый экземпляр.

3. Запрос: создает экземпляр компонента для одного HTTP-запроса.

4. Сеанс: создает экземпляр компонента для каждого сеанса HTTP.

5. Приложение: создает экземпляр компонента для жизненного цикла ServletContext.

6. WebSocket: создает экземпляр компонента для определенного сеанса WebSocket.

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

Жизненный цикл бина

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

  • Методы обратного вызова после инициализации
  • Методы обратного вызова перед уничтожением

Spring framework предоставляет следующие 4 способа управления событиями жизненного цикла bean-компонента:

  • Интерфейсы обратного вызова InitializingBean и DisposableBean
  • Осведомленные интерфейсы для определенного поведения (BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, ApplicationContextAware)
  • пользовательские методы init () и destroy () в файле конфигурации bean-компонента
  • Аннотации @PostConstruct и @PreDestroy

Жизненный цикл Spring Bean состоит из следующих этапов:

  1. Определение компонента: компонент определяется с помощью аннотаций или XML.
  2. Создание экземпляра компонента: Spring создает экземпляры объектов компонента точно так же, как если бы мы вручную создавали экземпляр объекта Java и загружали объект в ApplicationContext.
  3. Заполнение свойств компонента: Spring сканирует компоненты, которые реализуют интерфейсы Aware, и начинает устанавливать соответствующие свойства как идентификатор, область действия и значения по умолчанию на основе определения компонента.
  4. Предварительная инициализация. На этом этапе вступают в действие процессоры BeanPostProcessor. Методы postProcessBeforeInitialization () делают свое дело. Также сразу после них запускаются аннотированные методы @PostConstruct.
  5. AfterPropertiesSet: Spring выполняет методы afterPropertiesSet () компонентов, которые реализуют InitializingBean.
  6. Пользовательская инициализация: Spring запускает методы инициализации, которые мы определили в атрибуте initMethod наших аннотаций @Bean.
  7. Постинициализация: BeanPostProcessors Spring работают во второй раз. На этом этапе запускаются методы postProcessAfterInitialization ().
  8. Готово: теперь bean-компонент создан и внедрен во все зависимости.
  9. Pre-Destroy: Spring запускает аннотированные методы @PreDestroy на этом этапе.
  10. Destroy: Spring выполняет методы destroy () реализаций DisposableBean.
  11. Custom Destruction: мы можем определить пользовательские перехватчики уничтожения с атрибутом destroyMethod в аннотации @Bean, и Spring запускает их на последнем этапе.

Заключение

Это было краткое изложение того, что такое компонент Spring, как его можно использовать и его жизненный цикл. На самом деле, если вам это нужно, вы можете идти все глубже и глубже, потому что есть много других вещей, которые вы можете знать о Spring beans, но для того, чтобы начать работать со Spring и для повседневной жизни, этого достаточно. До встречи в следующей статье!

Другие статьи о Java и Spring, которые могут вам понравиться: