Java for Beginner
679 subscribers
577 photos
158 videos
12 files
876 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Основы Bean в Spring: создание и управление

Бин (Bean) в контексте Spring — это обычный Java-объект, который регистрируется в контейнере Spring и управляется им. Контейнер Spring создаёт экземпляры бинов, внедряет зависимости и управляет их жизненным циклом. Бины могут быть определены с помощью конфигурации в виде XML, аннотаций или Java-классов.

Основные компоненты, связанные с бинами в Spring:

Контейнер IoC: это ядро Spring, которое отвечает за создание и управление жизненным циклом бинов.
Конфигурация: способы описания бинов, которые могут быть как в виде XML-файлов, так и с использованием аннотаций или Java-конфигурации.
Внедрение зависимостей (Dependency Injection): механизм, при котором контейнер автоматически предоставляет объектам необходимые зависимости.


Способы создания бинов в Spring

Есть несколько способов создания и определения бинов в Spring:
Создание бина через XML-конфигурацию
Создание бина с помощью аннотаций


Java-классы для конфигурации бинов

1. Определение бина через XML-конфигурацию
Одним из старейших и всё еще актуальных способов создания бинов в Spring является использование XML-файлов. Бины описываются внутри специального XML-файла конфигурации, который передается контейнеру при запуске приложения.

Пример: создадим простое приложение для отправки сообщений.
public interface MessageService {
void sendMessage(String message);
}

public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("Отправка сообщения через Email: " + message);
}
}


XML-конфигурация (beans.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- Определение бина для EmailService -->
<bean id="emailService" class="com.example.EmailService"/>
</beans>


Использование бина:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

MessageService service = (MessageService) context.getBean("emailService");
service.sendMessage("Привет, Spring!");
}
}


2. Определение бина с помощью аннотаций


Современный и популярный способ создания бинов в Spring — это использование аннотаций. Аннотации позволяют конфигурировать бины непосредственно в коде, избавляя от необходимости создания XML-файлов.
import org.springframework.stereotype.Component;

@Component
public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("Отправка сообщения через Email: " + message);
}
}
Здесь мы используем аннотацию @Component, чтобы Spring автоматически зарегистрировал этот класс как бин.


Использование аннотаций для конфигурации:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

MessageService service = context.getBean(EmailService.class);
service.sendMessage("Привет, Spring с аннотациями!");
}
}


#Java #Training #Spring #Spring_Bean
3. Определение бина через Java-конфигурацию

Другой мощный способ — это использование конфигурационных классов. Аннотация
@Configuration позволяет заменить XML-файл Java-классом, в котором объявлены методы с аннотацией @Bean.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

@Bean
public MessageService emailService() {
return new EmailService();
}
}
Этот Java-класс полностью заменяет XML-конфигурацию.


Управление бинами в Spring

После того, как бины созданы и зарегистрированы в контейнере, Spring предоставляет множество возможностей для управления ими:
Внедрение зависимостей: Spring автоматически разрешает зависимости бинов, используя внедрение через конструктор, сеттеры или поля.
Скоуп бинов (Scopes):
Spring поддерживает несколько областей видимости для бинов, которые управляют временем жизни объектов.

Внедрение зависимостей

Spring поддерживает несколько типов внедрения зависимостей:
Через конструктор — наиболее предпочтительный метод.
Через сеттеры — позволяет внедрять зависимости после создания объекта.


Пример внедрения зависимости через конструктор:
@Component
public class MessageProcessor {

private final MessageService messageService;

@Autowired
public MessageProcessor(MessageService messageService) {
this.messageService = messageService;
}

public void processMessage(String message) {
messageService.sendMessage(message);
}
}


Пример внедрения зависимости через сеттер:
@Component
public class MessageProcessor {

private MessageService messageService;

@Autowired
public void setMessageService(MessageService messageService) {
this.messageService = messageService;
}

public void processMessage(String message) {
messageService.sendMessage(message);
}
}


Скоупы бинов

Spring поддерживает следующие основные скоупы для бинов:
Singleton — по умолчанию каждый бин создается в одном экземпляре для всего приложения.
Prototype — новый экземпляр бина создается каждый раз при запросе.


Пример указания скоупа через аннотацию:
@Component
@Scope("prototype")
public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println("Отправка сообщения через Email: " + message);
}
}


Lazy и Eager инициализация бинов

Spring предоставляет возможность управлять тем, когда именно создаются бины:
Eager инициализация — бины создаются сразу при старте контекста (по умолчанию).
Lazy инициализация — бины создаются только тогда, когда они впервые запрашиваются.


@Component
@Lazy
public class LazyService {
public LazyService() {
System.out.println("LazyService создан");
}
}
В данном случае бин LazyService не будет создан до тех пор, пока он не будет запрошен.


Преимущества управления бинами в Spring

Гибкость: Spring позволяет использовать различные подходы для создания и управления бинами, такие как аннотации, XML и Java-конфигурации.
Автоматизация: Контейнер
Spring автоматически управляет жизненным циклом бинов, что облегчает разработку сложных приложений.
Модульность: Каждый бин может быть независимо настроен и протестирован.


#Java #Training #Spring #Spring_Bean
Жизненный цикл бинов

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

Этапы жизненного цикла бина в Spring

Жизненный цикл бина включает в себя несколько стадий:
Создание бина: контейнер IoC создает объект и управляет его инициализацией.
Внедрение зависимостей: если у бина есть зависимости, они автоматически разрешаются и внедряются
Spring.
Пост-инициализация: дополнительные операции, которые можно выполнить после создания объекта.
Использование бина: бин может быть использован в приложении.
Уничтожение бина: при завершении работы приложения
Spring уничтожает бины.

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

Создадим пример с бином, который отправляет сообщения, и реализуем этапы его жизненного цикла.


Пример класса с методами инициализации и уничтожения:
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
public class MessageService {

public MessageService() {
System.out.println("Создание бина MessageService");
}

@PostConstruct
public void init() {
System.out.println("Инициализация бина MessageService");
}

public void sendMessage(String message) {
System.out.println("Отправка сообщения: " + message);
}

@PreDestroy
public void destroy() {
System.out.println("Уничтожение бина MessageService");
}
}


Объяснение этапов:
Конструктор: при создании бина вызывается конструктор класса. Здесь мы видим, что при создании бина выводится сообщение "Создание бина MessageService".
Аннотация
@PostConstruct: после создания бина и внедрения всех зависимостей вызывается метод, помеченный этой аннотацией. В нашем примере это метод init(), который выводит сообщение "Инициализация бина MessageService".
Методы бина: после инициализации бин может быть использован для выполнения своих задач. В данном случае это метод sendMessage(), который выводит сообщение.
Аннотация
@PreDestroy: перед уничтожением бина вызывается метод, помеченный аннотацией @PreDestroy. В нашем примере это метод destroy(), который выводит сообщение "Уничтожение бина MessageService".

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

Spring также предоставляет интерфейсы для более детального управления жизненным циклом бинов:
InitializingBean: интерфейс с методом afterPropertiesSet(), который вызывается после внедрения зависимостей.
DisposableBean: интерфейс с методом destroy(), который вызывается при завершении работы приложения для уничтожения бина.


Пример реализации этих интерфейсов:
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class CustomService implements InitializingBean, DisposableBean {

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Инициализация бина CustomService через afterPropertiesSet");
}

@Override
public void destroy() throws Exception {
System.out.println("Уничтожение бина CustomService через destroy");
}
}


#Java #Training #Spring #Spring_Bean_LifeCicle
Методы инициализации и уничтожения через XML

Если вы используете XML-конфигурацию, вы можете указать методы инициализации и уничтожения прямо в конфигурационном файле:
<bean id="messageService" class="com.example.MessageService" 
init-method="init" destroy-method="destroy"/>
Здесь init-method и destroy-method указывают на методы, которые будут вызваны при инициализации и уничтожении бина соответственно.


Singleton и Prototype: Различия в жизненном цикле

Spring поддерживает несколько типов скоупов для бинов, наиболее популярные из которых — это singleton и prototype. Жизненный цикл бинов в этих скоупах отличается:
Singleton: бин создается один раз при старте контейнера и существует на протяжении всего времени работы приложения.
Prototype: новый экземпляр бина создается каждый раз, когда он запрашивается.


@Component
@Scope("prototype")
public class PrototypeBean {

public PrototypeBean() {
System.out.println("Создан новый экземпляр PrototypeBean");
}
}
При каждом запросе PrototypeBean будет создаваться новый объект.


Способы ручного управления жизненным циклом бинов

Иногда возникает необходимость вручную управлять жизненным циклом бинов, например, для освобождения ресурсов. Это можно сделать, используя метод close() у контекста:
AnnotationConfigApplicationContext context = 
new AnnotationConfigApplicationContext(AppConfig.class);

MessageService service = context.getBean(MessageService.class);
service.sendMessage("Привет, Spring!");

context.close();
Метод close() завершает работу контекста и вызывает методы уничтожения всех бинов.

#Java #Training #Spring #Spring_Bean_LifeCicle
Что выведет код?

Задача по Spring. Тема: #Spring_Bean_LifeCicle. Сложность средняя.

Подробный разбор через 30 минут!🫡

public class Task221024_2 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig221024.class);
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething();
context.close();
}
}

@Component
class MyBean implements InitializingBean, DisposableBean {

public MyBean() {
System.out.println("Constructor called");
}

@Override
public void afterPropertiesSet() {
System.out.println("afterPropertiesSet (init) called");
}

public void doSomething() {
System.out.println("Doing something");
}

@Override
public void destroy() {
System.out.println("destroy (cleanup) called");
}
}

@Configuration
@ComponentScan()
class AppConfig221024 {}


#TasksSpring