Страницы

Поиск по вопросам

среда, 17 апреля 2019 г.

Разница между singleton в Java и в Spring

Наткнулась на такие строки про область видимости Singleton в Spring:
Note that there is a subtle difference between the instance obtained using the Java Singleton pattern and Spring Singleton. Spring Singleton is a singleton per context or container, whereas the Java Singleton is per process and per class loader.
Мой перевод:
Обратите внимание, что существует тонкая разница между экземпляром, полученным с использованием шаблона Java Singleton и Spring Singleton. Spring Singleton уникален в рамках контекста или контейнера, тогда как Java Singleton - в рамках процесса или загрузчика классов.
И, во-первых, хотелось бы удостовериться, что мой перевод правильный. А во-вторых, хотелось бы глубже понять разницу между singleton в Java и в Spring...


Ответ

Перевод верный.
Spring Singleton уникален в рамках контекста или контейнера
Это значит, что каждый раз, запрашивая singleton-бин из одного и того же контекста, вы будете получать один и тот же объект:
ApplicationContext ctx = new ClassPathXmlApplicationContext("/application-context.xml"); MySingleton s1 = ctx.getBean("mySingleton", MySingleton.class); MySingleton s2 = ctx.getBean("mySingleton", MySingleton.class); // s1 == s2
Но если синглтон будет получен из другого контекста или будет создан НЕ Spring'ом (через new или какой-нибудь другой контейнер), вы получите другой объект.
ApplicationContext ctx1 = new ClassPathXmlApplicationContext("/application-context.xml"); ApplicationContext ctx2 = new ClassPathXmlApplicationContext("/application-context.xml"); MySingleton s1 = ctx1.getBean("mySingleton", MySingleton.class); MySingleton s2 = ctx2.getBean("mySingleton", MySingleton.class); MySingleton s3 = new MySingleton(); // s1 != s2 // s2 != s3 // s1 != s3
Java Singleton уникален в рамках процесса или загрузчика классов
Это значит, что в рамках одного процесса JVM вы не сможете создать два разных экземпляра класса синглтона*. В этом случае сам класс-синглтон должен конроллировать процесс создания собственных экземпляров (в отличие от предыдущего случая, где этот процесс контроллируется контейнером Spring'а). Обычно этого добиваются, делая конструктор private и разрешая получать экземпляры класса только через статический метод этого класса, который всегда отдаёт один и тот же объект.
* Это можно попытаться обойти при помощи Reflections API, загрузки одного и того же класса несколькими classloader'ами (отсюда оговорка "в рамках загрузчика классов") или другими грязными хаками.

Комментариев нет:

Отправить комментарий