JavaRush /Курси /Модуль 5. Spring /Практика: створення конфігураційних класів і бінів

Практика: створення конфігураційних класів і бінів

Модуль 5. Spring
Рівень 2 , Лекція 7
Відкрита

Конфігураційні класи в Java замінюють старий підхід з XML-конфігурацією. Завдяки цьому налаштування Spring-застосунків стає більш читабельним і зручним.

Конфігураційний клас — це Java-клас, який використовується для опису конфігурації вашого застосунку. У Spring такі класи помічають анотацією @Configuration. Це дає IoC-контейнеру зрозуміти, що клас містить методи, які створюють біни. Ці методи помічені анотацією @Bean.

Конфігураційний клас можна уявити як меню вашої улюбленої кафешки. За допомогою @Bean ви описуєте, що буде подано на стіл (об'єкти), а IoC-контейнер виступає офіціантом, який доставить усе потрібне (впровадження залежностей) до вашого столика.

Приклад простого конфігураційного класу


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public String welcomeMessage() {
        return "Ласкаво просимо в Spring Framework!";
    }
}

У нашому прикладі welcomeMessage — це бін, який повертає рядок. Конфігураційний клас AppConfig містить метод, помічений анотацією @Bean, а Spring знає, що цей метод створює бін, яким керує IoC-контейнер.

Але не хвилюйтеся, ми не зупинимося на біні, який просто говорить вам "привіт". Ми ще розженемося і створимо складніші конфігурації.


Створення бінів і робота із залежностями

Конфігураційні класи корисні при створенні об'єктів, які мають залежності. Наприклад, якщо в нас є клас Car, і він залежить від двигуна Engine, ми можемо налаштувати це в конфігураційному класі.

Приклад із залежностями


public class Engine {
    private String type;

    public Engine(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

public class Car {
    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        System.out.println("Car is driving with " + engine.getType() + " engine.");
    }
}

Тепер створимо конфігураційний клас для цих об'єктів:


@Configuration
public class VehicleConfig {

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

    @Bean
    public Car car() {
        return new Car(engine());
    }
}

У методі car ми викликаємо метод engine, щоб передати його в конструктор класу Car. Це дозволяє Spring зрозуміти, що бін Car залежить від біна Engine. Тепер IoC-контейнер потурбується про те, щоб правильно налаштувати наш об'єкт.

Як це працює?

  1. Spring створює бін Engine з типом V8.
  2. Потім створюється бін Car, і в його конструктор автоматично передається бін Engine.

Цей зручний процес скорочує кількість коду, який ми писали б вручну. Чесно — мало кого би порадувало створювати всі залежності вручну.

Декларація залежностей між бінaми в явній формі

Якщо з якоїсь причини ви захочете явно вказати біну Car, що йому потрібен бін Engine, це можна зробити з анотацією @Qualifier (спойлер: знадобиться в наступних лекціях).


Складні залежності: біни, що залежать від декількох інших бінів

Припустимо, ми створюємо сервіс бронювання авіаквитків. Потрібно об'єднати кілька залежностей, наприклад клієнта для роботи з базою даних і сервіс оплати. Все це можна налаштувати в конфігураційному класі.


public class PaymentService {
    public void pay() {
        System.out.println("Платіж успішно оброблено!");
    }
}

public class BookingService {
    private PaymentService paymentService;

    public BookingService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void bookFlight() {
        System.out.println("Бронювання завершено.");
        paymentService.pay();
    }
}

Налаштуємо все це за допомогою конфігураційного класу:


@Configuration
public class BookingConfig {

    @Bean
    public PaymentService paymentService() {
        return new PaymentService();
    }

    @Bean
    public BookingService bookingService() {
        return new BookingService(paymentService());
    }
}

Тепер ми отримали:

  • Інкапсуляцію логіки створення об'єктів.
  • Мінімізацію коду в основній логіці застосунку.
  • Гнучкість: зміни в конфігурації легко адаптуються.

Запобігаємо проблемам із дублюванням бінів

Однією з поширених помилок є випадкове створення дублікатів бінів. Якщо ви спробуєте оголосити два біна з однаковим ім'ям, Spring видасть помилку: "Знайдено кілька кандидатів для впровадження залежності". Щоб цього уникнути, переконайтеся, що ваші методи @Bean мають унікальні імена і коректно описані.


Практика: налаштування реального проєкту

Давай зробимо крок у бік нашого навчального застосунку. Ми будемо створювати сервіс для керування книжками в бібліотеці, з використанням конфігураційного класу.

Бізнес-логіка


public class Book {
    private String title;
    private String author;

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book: " + title + " by " + author;
    }
}

public class LibraryService {
    private Book book;

    public LibraryService(Book book) {
        this.book = book;
    }

    public void displayBookInfo() {
        System.out.println(book.toString());
    }
}

Конфігураційний клас


@Configuration
public class LibraryConfig {

    @Bean
    public Book defaultBook() {
        return new Book("Clean Code", "Robert C. Martin");
    }

    @Bean
    public LibraryService libraryService() {
        return new LibraryService(defaultBook());
    }
}

Використання у головному застосунку


import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

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

        LibraryService libraryService = context.getBean(LibraryService.class);
        libraryService.displayBookInfo();
    }
}

Підсумковий вивід програми:


Book: Clean Code by Robert C. Martin

Вітаю! Ми розглянули, як використовувати конфігураційні класи і створювати Spring Beans. Тепер ви можете конструювати об'єкти, зв'язувати їхні залежності і змусити IoC-контейнер працювати на вас.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ