Как внедрить Prototype в Singleton в Spring с помощью параметра ProxyMode

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Довольно популярный вопрос на собеседовании - Можно ли внедрить Prototyte в Singleton и как это сделать?

Если просто добавить к определению бина аннотацию @Scope(SCOPE_PROTOTYPE), и использовать этот бин в синглтоне через аннотацию @Autowired – будет создан только один объект. Потому что синглтон создается только однажды, и обращение к прототипу случится тоже однажды при его создании (при внедрении зависимости).

На самом деле вариантов довольно много:

  • с помощью @Lookup

  • context.getBean(Prototype.class)

  • API -интерфейс javax.inject

  • Интерфейс ObjectFactory 

Но эти варианты мягко скажем "не очень".

В некоторых статьях пишут что можно сделать это с помощью параметра ProxyMode в аннотации @Scope, но я не смог найти реальных примеров внедрения, so напишу свой.

Для начала создадим наш будущий Prototype.

  • Каждый раз когда создается новый экземпляр будем выводить в консоль "new bank created".

  • Добавим @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,proxyMode = TARGET_CLASS)

    Выражение proxyMode=TARGET_CLASS oзначает, что класс создается с помощью наследования.

    Можно сделать proxyMode = INTERFACES, тогда proxy создастся c использованием интерфейсов, наш класс не реализует никаких интерфейсов(интерфейсы - маркеры не подойдут), поэтому используем TARGET_CLASS.

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.UUID;

import static org.springframework.context.annotation.ScopedProxyMode.TARGET_CLASS;

/**
 * Created in SoftMediaLab
 * by Mark Ponomarev
 * Date : 15.09.2023
 **/

@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode=TARGET_CLASS)
public class Bank {

    private final String bankName;

    public Bank() {
        this.bankName = UUID.randomUUID().toString();
        System.out.println("new bank created");
    }

    public String getInput() {
        return bankName;
    }
}

Сейчас создадим Singleton.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Created in SoftMediaLab
 * by Mark Ponomarev
 * Date : 15.09.2023
 **/

@Service()
public class BankService {

    @Autowired
    Bank bank;

    public Bank getNewBank(){
        return bank;
    }
  
}

Тут все довольно просто, Мы инжектим наш Prototype c помощью aннотации @Autowired.

Для проверки напишем дополнительный метод.

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;



@SpringBootTest
class PrimaryExampleApplicationTests {
    @Autowired
    BankService messageService;

    @Test
    public void testing(){
        Bank newBank1 = messageService.getNewBank();
        Bank newBank = messageService.getNewBank();
        System.out.println(newBank.getInput());
        System.out.println(newBank1.getInput());
    }
}

Можете самостоятельно проверить, что будет создано 2 экземпляра класса Bank.

Для полноты картины вы можете самостоятельно внедрить Prototype, используя динамический Proxy(proxyMode = INTERFACES). Не забудьте про то, что нужно реализовать интерфейс, иначе будет Exeption при поднятии контекста.

Источник: https://habr.com/ru/articles/761330/


Интересные статьи

Интересные статьи

Эта статья рассчитана на Spring Boot разработчиков, желающих пощупать мир современного фронтенда. Я потратил некоторое количество времени на поиск наиболее приличного фреймворка и мой выбор пал на Sve...
Несколько лет назад в интернет-магазине книг я случайно увидел книгу Михаила Бородянского под названием “8 цветных психотипов: Кто вы? Векторная психология”. Я приобрел данную книгу и прочитал ее. На ...
Ничто не бодрит с утра лучше, чем большая техническая конференция по JavaScript. Восьмого июня в 11:40 стартовала онлайн-часть HolyJS. Получилось огненно (во всех смыслах), весело и познавательно. И т...
Привет! На связи Евгений Бокарев и Надежда Грачёва, в этой статье мы расскажем про внедрение switchback A/B-тестов в логистике Delivery Club. Обсудим, как оценивать результат эксперимента, если эффект...
Мы в JSOC CERT ежедневно сталкиваемся с событиями из разных песочниц, которые функционируют в составе AntiAPT-решений наших заказчиков и пропускают через себя тысячи файлов из web- и почтового тр...