Is spring default scope singleton or not?

半城伤御伤魂 提交于 2019-11-26 08:14:29

问题


Could you please explain why Spring is creating two objects for the configuration of beans shown below, since by default spring default scope is singleton?

The Spring configuration is here:

<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>

回答1:


Spring's default scope is singleton. It's just that your idea of what it means to be a singleton doesn't match how Spring defines singletons.

If you tell Spring to make two separate beans with different ids and the same class, then you get two separate beans, each with singleton scope. All singleton scope means is that when you reference something with the same id, you get the same bean instance back.

Here is how the Spring documentation defines singleton scope:

Only one shared instance of a singleton bean is managed, and all requests for beans with an id or ids matching that bean definition result in that one specific bean instance being returned by the Spring container.

Singleton scope means using the same id retrieves the same bean, that is all. Testing that no two ids referenced the same class would get in the way of using maps as beans, and would be complicated by proxying things with BeanFactories. For Spring to police this would involve a lot of work for little benefit, instead it trusts the users to know what they're doing.

The way to define two names for the same bean is to use an alias:

In a bean definition itself, you can supply more than one name for the bean, by using a combination of up to one name specified by the id attribute, and any number of other names in the name attribute. These names can be equivalent aliases to the same bean, and are useful for some situations, such as allowing each component in an application to refer to a common dependency by using a bean name that is specific to that component itself.

Specifying all aliases where the bean is actually defined is not always adequate, however. It is sometimes desirable to introduce an alias for a bean that is defined elsewhere. This is commonly the case in large systems where configuration is split amongst each subsystem, each subsystem having its own set of object definitions. In XML-based configuration metadata, you can use the element to accomplish this.

So if you add a name in the bean configuration:

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

or create an alias for a bean defined elsewhere:

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

then "customer" and "customer2" will refer to the same bean instance.




回答2:


Spring default scope is singleton and it will create one object for all instances unless you explicitly specify the scope to be prototype. You have not posted spring configuration. Please post it, it will give a better idea.




回答3:


You are declaring two beans of the same class. That isn't the same.

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

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

}

And try to access this bean in two places the number will be the same. But what you have done was creating two separate beans.

If you want to check if this works try:

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());
   }
}

This code should return true if it is same instance; But in SpringTestClass you can add @Scope("prototype") annotation. The output will be false




回答4:


Like others have mentioned, two beans should be created from the code you posted. Singletons are defined as follows (from the Spring documentation: Singleton Scope)

Only one shared instance of a singleton bean is managed, and all requests for beans with an id or ids matching that bean definition result in that one specific bean instance being returned by the Spring container.

To add clarity to this, the meaning behind "shared instance" is explained in the paragraph that follows the one above:

all subsequent requests and references for that named bean return the cached object

When a singleton bean is created, only one bean object is instantiated and cached. This refers only to the bean, not to whatever class the bean may be an instance of. For example,

<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>

In this made up configuration, "myOtherBean1" and "myOtherBean2" have references to the same "myBean" bean therefore the same "myPackage.myClass" instance. If you changed the code to add a second "myPackage.myClass" bean, it would be distinct from "myBean".

To fully understand this, also refer to the other Spring scope: the prototype. From the Spring documentation for Prototype Scope:

The non-singleton, prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made.

This means that if we were to use the same Spring XML as above, "myOtherBean1" and "myOtherBean2" would each receive their own distinct copies of "myBean" which is still just an instance of "myPackage.myClass".




回答5:


You're confusing two different concepts.

The word singleton in spring is used for a bean scope, meaning that the bean will be created only once for the whole application.

Singleton usual meaning refers to the GOF pattern. It is an object oriented pattern guarantying that only one instance of a class will exists (at least in the scope of the classLoader).




回答6:


The following example shows a @Bean annotated method being called twice:

@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() has been called once in clientService1() and once in clientService2(). Since this method creates a new instance of ClientDaoImpl and returns it, you would normally expect having 2 instances (one for each service). That definitely would be problematic: in Spring, instantiated beans have a singleton scope by default. This is where the magic comes in: All @Configuration classes are subclassed at startup-time with CGLIB. In the subclass, the child method checks the container first for any cached (scoped) beans before it calls the parent method and creates a new instance. Note that as of Spring 3.2, it is no longer necessary to add CGLIB to your classpath because CGLIB classes have been repackaged under org.springframework.cglib and included directly within the spring-core JAR.




回答7:


In SPring Singleton referes to One bean per Spring container where as in Java Singleton refers to one object per class loader.

So Spring singleton is not same as java singleton. Don't get confused between these two.




回答8:


Spring Singleton Bean Does not work like Java Singleton.

If we write

ApplicationContext ctx = new ClassPathXmlApplicationContext("MyConfig.xml");
        Customer obj1= (Customer) ctx.getBean("customer");
        Customer obj2 = (Customer) ctx.getBean("customer2");
        System.out.println(obj1 == obj2);
        System.out.println(obj1+ "::" + obj2);

If we see the output it will return 2 different Instance. According to Spring Docs Bean is singleton only one shared Instance will be managed, and all request beans with an ID or ID matching that bean definition. Here 2 different ID is available.

Spring container as managing Key value pair, Key as ID/Name and value is bean.



来源:https://stackoverflow.com/questions/31629993/is-spring-default-scope-singleton-or-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!