1. Повторне знайомство зі Spring Beans
Spring Bean — це, по суті, об'єкт, яким керує IoC-контейнер Spring. Ці об'єкти створюються, ініціалізуються, налаштовуються, а також видаляються контейнером залежно від конфігурації програми. Якщо хочеш, щоб твій Java-об'єкт став частиною магії Spring, його треба зареєструвати як bean.
Уяви менеджера на складі, який завжди знає, де лежить потрібний тобі інструмент (або об'єкт). Ось таким менеджером і є IoC-контейнер, а інструменти на складі — це наші біни.
Як реєструються beans у Spring?
Є кілька способів зареєструвати біни:
- Анотації (наприклад,
@Component,@Service,@Repository). - Java-based конфігурація з використанням
@Configurationі@Bean. - XML-конфігурація (так, вона все ще є, але використовується рідше — навіщо, коли є Java-анотації?).
Ось чому Spring гнучкий — обирай зручний спосіб реєстрації бінів.
2. Життєвий цикл Spring Bean
Біни, як і всі живі організми, мають життєвий цикл. Цей життєвий шлях включає етапи створення, ініціалізації, використання і видалення — все це контролюється IoC-контейнером. Давай розберемося, як це працює.
Основні етапи життєвого циклу
- Створення: bean створюється IoC-контейнером.
- Ініціалізація: у цей момент bean може налаштувати свої внутрішні стани.
- Використання: bean починає виконувати свою роботу (наприклад, обробляє запити).
- Видалення: як тільки bean більше не потрібен, контейнер видаляє його (якщо, звісно, це не singleton).
Візуалізація життєвого циклу
1. Створення об'єкта
↓
2. Встановлення залежностей (DI)
↓
3. Виклик методів ініціалізації (@PostConstruct)
↓
4. Використання біну
↓
5. Очищення ресурсів (@PreDestroy)
Тепер давай розглянемо конкретний приклад.
3. Як Spring керує життєвим циклом?
Для цього у Spring є зручні анотації. Познайомимося з ключовими з них.
Анотації @PostConstruct і @PreDestroy
@PostConstruct: виконує дії після створення bean і встановлення всіх його залежностей (наприклад, підключає сервіс або завантажує дані).@PreDestroy: спрацьовує перед видаленням bean. Використовується для звільнення ресурсів (наприклад, закриття з'єднань).
Приклад:
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class LifecycleDemoBean {
@PostConstruct
public void init() {
System.out.println("Бін ініціалізовано!");
}
public void doSomething() {
System.out.println("Бін працює!");
}
@PreDestroy
public void cleanup() {
System.out.println("Бін знищено!");
}
}
Коли Spring бачить анотації @PostConstruct і @PreDestroy, він гарантує, що ці методи будуть викликані у відповідні моменти.
Альтернатива з інтерфейсами InitializingBean і DisposableBean
Якщо віддаєш перевагу інтерфейсам замість анотацій (наприклад, для більш явного контракту), можна використати:
InitializingBean— методafterPropertiesSet()викликається після створення bean.DisposableBean— методdestroy()викликається перед видаленням bean.
Приклад:
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class AlternativeLifecycleBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Об'єкт налаштовано (InitializingBean)!");
}
@Override
public void destroy() throws Exception {
System.out.println("Об'єкт знищено (DisposableBean)!");
}
}
Хоча такий підхід працює, у сучасних проєктах частіше використовують анотації @PostConstruct і @PreDestroy за їхню простоту і читабельність.
4. Керування бінaми за допомогою анотацій
@Component і компанія
@Component: загальна анотація для будь-якого біну, яку застосовують, якщо спеціалізована анотація не підходить.@Service: для класів з бізнес-логікою.@Repository: для класів, що відповідають за доступ до даних.@Controller: для MVC-контролерів.
Приклад використання @Component:
@Component
public class SimpleBean {
public void sayHello() {
System.out.println("Привіт, світ бінів!");
}
}
@Autowired і автоматичне впровадження залежностей
Ми вже трохи говорили про впровадження залежностей, але давай заглибимось.
@Autowired: дозволяє Spring автоматично налаштувати залежності.
Приклад роботи з @Autowired:
@Component
public class DependencyBean {
public String getDependencyInfo() {
return "Інформація про залежність.";
}
}
@Component
public class AutowiredBean {
private final DependencyBean dependency;
@Autowired
public AutowiredBean(DependencyBean dependency) {
this.dependency = dependency;
}
public void printDependencyInfo() {
System.out.println(dependency.getDependencyInfo());
}
}
При запуску Spring сам знайде DependencyBean і передасть його в AutowiredBean.
5. Скоупи бінів
За замовчуванням усі біни в Spring мають scope singleton. Це означає, що існує тільки один екземпляр біна в IoC-контейнері. Але іноді треба керувати scope'ами.
Основні scope'и
- Singleton: один бін на весь IoC-контейнер.
- Prototype: новий об'єкт створюється щоразу, коли бін запитується.
- Request: один екземпляр для кожного HTTP-запиту.
- Session: один екземпляр для кожної HTTP-сесії.
Встановлення scope'у
Анотація @Scope дозволяє керувати життєвим циклом біна.
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class PrototypeBean {
public PrototypeBean() {
System.out.println("Створено новий екземпляр PrototypeBean!");
}
}
Кожного разу при використанні цього біна створюється новий екземпляр.
6. Типові помилки і як їх виправити
- Помилка через відсутність залежності: якщо використовуєш
@Autowired, але бін не зареєстрований, Spring кине винятокNoSuchBeanDefinitionException. Рішення? Перевір, що бін зареєстрований через анотацію або конфігурацію. - Видалення prototype-біну: Spring не керує життєвим циклом
prototype-бінів, тому видаляй їх самостійно. - Багато співпадінь бінів: якщо в тебе кілька бінів одного типу, Spring може заплутатися. Використовуй
@Qualifier, щоб вказати конкретний бін.
Приклад @Qualifier:
@Component("catBean")
public class Cat {}
@Component("dogBean")
public class Dog {}
@Component
public class AnimalShelter {
@Autowired
@Qualifier("catBean") // Вказуємо, який бін використовувати
private Cat pet;
}
Звідки ми це все знаємо?
Якщо хочеш копати глибше, ось кілька корисних посилань:
Хай живуть біни, життєвий цикл і те, що спрощує нам життя! Наступний крок — ще більше магії Spring!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ