it-swarm.com.ru

Весной по умолчанию сфера синглтон или нет?

Не могли бы вы объяснить, почему Spring создает два объекта для конфигурации bean-компонентов, показанных ниже, поскольку по умолчанию область действия Spring по умолчанию - singleton?

Конфигурация Spring здесь:

<bean id="customer" class="jp.ne.goo.beans.Customer"> 
    <property name="custno" value="100"></property>
    <property name="custName" value="rajasekhar"> </property>
</bean>
<bean id="customer2" class="jp.ne.goo.beans.Customer"> 
    <property name="custno" value="200"></property> 
    <property name="custName" value="siva"></property> 
</bean>
33
Raj

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

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

Вот как в документации Spring определяется одноэлементная область :

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

Одиночная область означает, что при использовании одного и того же идентификатора извлекается один и тот же компонент, то есть все. Проверка того, что никакие два идентификатора, ссылающиеся на один и тот же класс, не помешают использовать карты в качестве bean-компонентов, и будет затруднена из-за использования прокси-объектов с BeanFactories. доверяет пользователям знать, что они делают.

Способ определить два имени для одного и того же компонента - использовать псевдоним :

В самом определении bean-компонента вы можете указать более одного имени для bean-компонента, используя комбинацию из одного имени, указанного в атрибуте id, и любого количества других имен в атрибуте name. Эти имена могут быть эквивалентными псевдонимами одного и того же компонента и могут быть полезны в некоторых ситуациях, например, позволяя каждому компоненту в приложении ссылаться на общую зависимость, используя имя компонента, специфичное для самого этого компонента.

Однако указание всех псевдонимов, в которых фактически определен компонент, не всегда адекватно. Иногда желательно ввести псевдоним для компонента, который определен в другом месте. Это обычно имеет место в больших системах, где конфигурация разделена между каждой подсистемой, каждая подсистема имеет свой собственный набор определений объектов. В метаданных конфигурации на основе XML вы можете использовать этот элемент для достижения этой цели.

Так что, если вы добавите имя в конфигурации бина:

<bean id="customer" name="customer2" 
    class="jp.ne.goo.beans.Customer">
</bean>

или создайте псевдоним для bean-компонента, определенного в другом месте:

<alias name="customer" alias="customer2"/>

тогда «customer» и «customer2» будут ссылаться на один и тот же экземпляр компонента.

45

Область Spring по умолчанию - singleton, и она создаст один объект для всех экземпляров, если вы явно не укажете область, которая будет прототипом. Вы не опубликовали весеннюю конфигурацию. Пожалуйста, отправьте это, это даст лучшую идею.

6
Anupama Rao

Вы объявляете два боба одного класса. Это не то же самое.

@Component("springTestClass")
public class SpringTestClass{
     private int randomNumber = 0;
     public SpringTestClass(){
       randomNumber = new Random().nextInt(2000);
     }

     public int getRandomNumber(){
       return this.randomNumber;
     }

}

И попробуйте получить доступ к этому бину в двух местах, число будет одинаковым. Но вы создали два отдельных компонента.

Если вы хотите проверить, работает ли это, попробуйте:

public class Main{
   public static void main(String[] args){
     ApplicationContext ctx = ....;
     SpringTestClass testObject1 = (SpringTestClass)ctx.getBean("springTestClass");
     SpringTestClass testObject2 = (SpringTestClass)ctx.getBean("springTestClass");

    System.out.println(testObject1.getRandomNumber() == testObject2.getRandomNumber());
   }
}

Этот код должен возвращать true, если это тот же экземпляр; Но в SpringTestClass вы можете добавить аннотацию @Scope ("prototype"). Вывод будет ложным

2
Berrigan

Как уже упоминалось, два бина должны быть созданы из кода, который вы разместили. Синглтоны определяются следующим образом (из документации Spring: Singleton Scope )

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

Чтобы внести ясность в это, значение, стоящее за «общим экземпляром», поясняется в параграфе, который следует за приведенным выше:

все последующие запросы и ссылки для этого именованного компонента возвращают кешированный объект

При создании одноэлементного компонента создается и кэшируется только один объект компонента. Это относится только к бобу, а не к тому классу, экземпляром которого может быть боб. Например,

<bean id="myBean" class="myPackage.myClass" />

<bean id="myOtherBean1 class="myPackage.myOtherClass1">
    <property name="beanReference1" ref="myBean" />
</bean>
<bean id="myOtherBean2 class="myPackage.myOtherClass2">
    <property name="beanReference2" ref="myBean" />
</bean>

В этой составленной конфигурации «myOtherBean1» и «myOtherBean2» имеют ссылки на один и тот же компонент «myBean», поэтому один и тот же экземпляр «myPackage.myClass». Если вы изменили код для добавления второго компонента «myPackage.myClass», он будет отличаться от «myBean».

Чтобы полностью понять это, также обратитесь к другой области Spring: прототип. Из документации Spring для Область применения прототипа :

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

Это означает, что если бы мы использовали тот же Spring XML, что и выше, «myOtherBean1» и «myOtherBean2» каждый получал бы свои собственные отдельные копии «myBean», который все еще является просто экземпляром «myPackage.myClass».

2
ryoung10

Вы путаете две разные концепции.

Синглтон Word весной используется для области действия компонента, что означает, что компонент будет создан только один раз для всего приложения. 

Обычное значение синглтона относится к шаблону GOF. Это объектно-ориентированный шаблон, гарантирующий, что будет существовать только один экземпляр класса (по крайней мере, в области действия classLoader). 

1
Gab

В следующем примере показано, как вызывается аннотированный метод @Bean дважды:

@Configuration
public class AppConfig {

    @Bean
    public ClientService clientService1() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientService clientService2() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientDao clientDao() {
        return new ClientDaoImpl();
    }

}

clientDao () вызывался один раз в clientService1 () и один раз в clientService2 (). Так как этот метод создает новый экземпляр ClientDaoImpl и возвращает его, вы обычно ожидаете иметь 2 экземпляры (по одному на каждую услугу). Это определенно было бы проблематично: весной экземпляры bean-компонентов имеют одноэлементную область видимости дефолт. Вот где приходит волшебство: все классы @Configuration подклассы во время запуска с CGLIB. В подклассе ребенок Метод сначала проверяет контейнер на наличие кэшированных (scoped) bean-компонентов перед он вызывает родительский метод и создает новый экземпляр. Обратите внимание, что с Spring 3.2, больше нет необходимости добавлять CGLIB в ваш путь к классам потому что классы CGLIB были переупакованы в org.springframework.cglib и включен непосредственно в ядро ​​пружины JAR.

0
Adam Ostrožlík