Шаблон проектирования Singleton против контейнера Singleton в контейнере Spring - PullRequest
86 голосов
/ 14 апреля 2010

Как все мы знаем, у нас есть bean-компоненты как синглтон по умолчанию в контейнере Spring, и если у нас есть веб-приложение, основанное на Spring Framework, тогда в этом случае нам действительно нужно реализовать шаблон проектирования Singleton для хранения глобальных данных, а не просто создавать боб через весну.

Пожалуйста, потерпите меня, если я не смогу объяснить, что я на самом деле хотел спросить.

Ответы [ 10 ]

54 голосов
/ 15 апреля 2010

Синглтон-бин весной и шаблон синглтона совершенно различны. Шаблон Singleton говорит, что один и только один экземпляр определенного класса будет создан для каждого загрузчика классов.

Область применения синглтона Spring описывается как "на контейнер на боб". Это область определения компонента для отдельного экземпляра объекта на контейнер Spring IoC. Область по умолчанию в Spring - Singleton.

Несмотря на то, что область по умолчанию - одноэлементная, вы можете изменить область действия bean-компонента, указав атрибут scope для элемента <bean ../>.

<bean id=".." class=".." scope="prototype" />
28 голосов
/ 20 июня 2012

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


И Spring не беспокоит, закодирован ли класс компонента как синглтон или нет, фактически, если класс закодирован как синглтон, конструктор которого является закрытым, Spring использует BeanUtils.instantiateClass (javadoc здесь ) конструктор для доступа и вызова его.

В качестве альтернативы, мы можем использовать атрибут фабричного метода в определении компонента, например:

    <bean id="exampleBean" class="example.Singleton"  factory-method="getInstance"/>
18 голосов
/ 08 мая 2014

Давайте рассмотрим самый простой пример: у вас есть приложение, и вы просто используете загрузчик классов по умолчанию. У вас есть класс, который, по какой-либо причине, вы решаете, что он не должен иметь более одного экземпляра в приложении. (Вспомните сценарий, в котором над приложениями работают несколько человек).

Если вы не используете среду Spring, шаблон Singleton гарантирует, что в вашем приложении будет не более одного экземпляра класса. Это потому, что вы не можете создать экземпляры класса, выполнив команду «new», потому что конструктор является закрытым. Единственный способ получить экземпляр класса - вызвать некоторый статический метод класса (обычно называемый «getInstance»), который всегда возвращает один и тот же экземпляр.

Утверждение, что вы используете в своем приложении среду Spring, просто означает, что в дополнение к обычным способам получения экземпляра класса (новые или статические методы, которые возвращают экземпляр класса), вы также можете задать Spring чтобы получить экземпляр этого класса, Spring гарантирует, что всякий раз, когда вы запрашиваете экземпляр этого класса, он всегда будет возвращать один и тот же экземпляр, даже если вы не написали класс с использованием шаблона Singleton. Другими словами, даже если у класса есть открытый конструктор, если вы всегда запрашиваете у Spring экземпляр этого класса, Spring будет вызывать этот конструктор только один раз в течение жизни вашего приложения.

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

Если вы действительно хотите один экземпляр класса, даже если вы используете Spring в своем приложении и определяете класс в Spring как singleton, единственный способ убедиться, что он также реализует класс с использованием шаблона Singleton. Это гарантирует, что будет один экземпляр, независимо от того, используют ли пользователи Spring для получения экземпляра или обходят Spring.

10 голосов
/ 14 апреля 2010

Область видимости Singleton в Spring означает, что Spring будет создан только один раз. В отличие от области прототипа (каждый раз новый экземпляр), область запроса (один раз на запрос), область сеанса (один раз на сеанс HTTP).

Область применения Singleton технически не связана с шаблоном проектирования Singleton. Вам не нужно реализовывать ваши bean-компоненты как синглтоны, чтобы их помещали в синглтонную область.

4 голосов
/ 01 января 2018

Мне трудно понять, "на контейнер на боб". Я бы сказал «один бин на идентификатор бина». Пусть есть пример, чтобы понять это. У нас есть образец класса бобов. Я определил два bean-компонента из этого класса в определении bean-компонента, например:

<bean id="id1" class="com.example.Sample" scope="singleton">
        <property name="name" value="James Bond 001"/>    
</bean>    
<bean id="id7" class="com.example.Sample" scope="singleton">
        <property name="name" value="James Bond 007"/>    
</bean>

Поэтому, когда бы я ни пытался получить бин с идентификатором "id1", контейнер пружины создаст один бин, кеширует его и вернет тот же боб, где когда-либо использовался id1. Если я попытаюсь получить его с помощью id7, из класса Sample будет создан другой компонент, который будет кэшироваться и возвращаться каждый раз, когда вы ссылаетесь на него с помощью id7.

Это маловероятно для шаблона Singleton. В шаблоне Singlton всегда создается один объект на загрузчик классов. Но весной многие объекты создаются для одного класса. Однако в Spring создается область видимости, как в Singleton, возвращая один и тот же объект для того же идентификатора. Ссылки

2 голосов
/ 29 января 2019

Существует очень фундаментальное различие между ними. В случае шаблона разработки Singleton будет создан только один экземпляр класса для каждого classLoader, в то время как в случае синглтона Spring это не так, как в последующем создан один экземпляр общего компонента для данного идентификатора для контейнера IoC.

Например, если у меня есть класс с именем «SpringTest» и мой XML-файл выглядит примерно так: -

<bean id="test1" class="com.SpringTest" scope="singleton">
        --some properties here
</bean>    
<bean id="test2" class="com.SpringTest" scope="singleton">
        --some properties here   
</bean>

Так что теперь в главном классе, если вы проверите ссылку на вышеупомянутые два, он вернет false в соответствии с документацией Spring: -

Когда бин является синглтоном, только один общий экземпляр бина будет быть управляемым, и все запросы для bean-компонентов с идентификатором или идентификаторами, соответствующими определение компонента приведет к тому, что один конкретный экземпляр компонента будет возвращенный контейнером Spring

Так что, как и в нашем случае, классы одинаковы, но идентификаторы, которые мы предоставили, отличаются, что приводит к созданию двух разных экземпляров.

2 голосов
/ 27 ноября 2012

Синглтон-бины в Spring и классы, основанные на шаблоне проектирования Singleton, весьма различны.

Шаблон Singleton гарантирует, что один и только один экземпляр определенного класса будет когда-либо создаваться для загрузчика классов, а область действия одноэлементного компонента Spring описывается как «на контейнер для компонента». Синглтонная область в Spring означает, что Spring будет создан только один раз. Контейнер Spring просто снова и снова возвращает один и тот же экземпляр для последующих вызовов, чтобы получить бин.

1 голос
/ 24 ноября 2017

Синглтон-бин Spring описывается как «на контейнер на боб». Область Singleton в Spring означает, что один и тот же объект в той же ячейке памяти будет возвращен с тем же идентификатором компонента. Если создается несколько бинов с разными идентификаторами одного и того же класса, контейнер возвращает разные объекты с разными идентификаторами. Это похоже на отображение значения ключа, где ключ - это идентификатор компонента, а значение - объект компонента в одном контейнере пружины. Где шаблон Singleton гарантирует, что один и только один экземпляр определенного класса когда-либо будет создан для загрузчика классов.

1 голос
/ 16 сентября 2015

EX: "за контейнер на боб".

        <bean id="myBean" class="com.spring4hibernate4.TestBean">
            <constructor-arg name="i" value="1"></constructor-arg>
            <property name="name" value="1-name"></property>
        </bean>

        <bean id="testBean" class="com.spring4hibernate4.TestBean">
            <constructor-arg name="i" value="10"></constructor-arg>
            <property name="name" value="10-name"></property>
        </bean>
    </beans>



    public class Test {

        @SuppressWarnings("resource")
        public static void main(String[] args) {
            ApplicationContext ac = new ClassPathXmlApplicationContext("ws.xml");
            TestBean teatBean = (TestBean) ac.getBean("testBean");
            TestBean myBean1 = (TestBean) ac.getBean("myBean");
            System.out.println("a : " + teatBean.test + " : "   + teatBean.getName());
            teatBean.setName("a TEST BEAN 1");
            System.out.println("uPdate : " + teatBean.test + " : "  + teatBean.getName());
            System.out.println("a1 : " + myBean1.test + " : " + myBean1.getName());
            myBean1.setName(" a1 TEST BEAN 10");
            System.out.println("a1 update : " + teatBean.test + " : " + myBean1.getName());
        }
    }

public class TestBean {
    public int test = 0;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name = "default";

    public TestBean(int i) {
        test += i;
    }
}

JAVA SINGLETON:

public class Singleton {
    private static Singleton singleton = new Singleton();
    private int i = 0;

    private Singleton() {
    }

    public static Singleton returnSingleton() {

        return singleton;
    }

    public void increment() {
        i++;
    }

    public int getInt() {
        return i;
    }
}

public static void main(String[] args) {
        System.out.println("Test");

        Singleton sin1 = Singleton.returnSingleton();
        sin1.increment();
        System.out.println(sin1.getInt());
        Singleton sin2 = Singleton.returnSingleton();
        System.out.println("Test");
        sin1.increment();
        System.out.println(sin1.getInt());
    }
1 голос
/ 01 октября 2010

"singleton" весной использует экземпляр фабрики bean, затем кеширует его; какой шаблон проектирования синглтона строго, экземпляр может быть извлечен только из статического метода get, и объект никогда не может быть публично создан.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...