When defining Java bean in Spring xml configuration or using the Spring annotation we can
mark a Java bean as singleton
or prototype
.
If a Java bean is marked as singleton, each time we call to get the bean we get the same instance.
If a Java bean is marked as prototype, each time we will get a new instance.
The following code defines a Java bean with a String type property.
package com.java2s.common; public class MyService { String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
If no bean scope is specified in bean configuration file, default to singleton.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.java2s.common.MyService" /> </beans>
Here is the code to run the xml configuration defined above.
package com.java2s.common; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main( String[] args ) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"SpringBeans.xml"}); MyService customerA = (MyService)context.getBean("customerService"); customerA.setMessage("Message by customerA"); System.out.println("Message : " + customerA.getMessage()); //retrieve it again MyService custB = (MyService)context.getBean("customerService"); System.out.println("Message : " + custB.getMessage()); } }
Output
Message : Message by customerA Message : Message by customerA
The code above get MyService
twice from the ApplicationContext
.
And it sets a String value for the message after the first call.
From the output we can see that both getMessage() call return the same message, which means
the ApplicationContext uses one copy of the MyService
.
If a bean is a singleton scope in Spring IoC container, getBean() will always return the same instance.
To get a new 'customerService' bean instance every time we call getBean(), use prototype scope.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.java2s.common.MyService" scope="prototype"/> </beans>
Run it again
From the output we can see that the second call to the context.getBean("customerService");
we got a new instance of MyService
.
The following code shows how to use the annotation to mark the bean scope.
package com.java2s.common; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @Service @Scope("prototype") public class MyService { String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
The following code shows how to enable auto component scanning.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="com.java2s.common" /> </beans>
Here is the new App.java class to run the configuration above.
The customerService
is changed to myService
.
Spring automatically creates a bean name from the class name by lower case the first
letter.
package com.java2s.common; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main( String[] args ) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"SpringBeans.xml"}); MyService customerA = (MyService)context.getBean("myService"); customerA.setMessage("Message by customerA"); System.out.println("Message : " + customerA.getMessage()); //retrieve it again MyService custB = (MyService)context.getBean("myService"); System.out.println("Message : " + custB.getMessage()); } }
Run it again