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>
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.
If you want a bean’s singleton-ness preserved across multiple names, that is do-able. You can have more than one name refer to the same bean, that is done by using 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.
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.
In Spring Singleton refers 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.
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).
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
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".
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.
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.
spring default scope is singleton. Once the bean will be created and same bean used throughout its lifecycle.
Related
Hello guys I am trying to understand how exactly prototype Scope works in Spring IoC.
For prototype beans I tried to understand by:
1. Reading this again and again but could not understand fully(https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-scopes-other-injection)
2. Tried to debug via source code,only understood one thing if we do not specify proxyMode, it will not create proxy for prototype bean.
3. default ScopedProxyMode for prototype scope is DEFAULT which typically equals NO.. unless configured in component scan.
So I have 3 examples here:
Case A: Prototype bean used independently(not having any dependency or is not dependency for any bean) without proxymode defined
#Bean
#Scope("prototype")
public Employee employee(){
return new Employee();
}
Case B: Prototype bean inside a singleton bean as dependency without proxymode defined
#Bean
#Scope("prototype")
public Employee employee(){
return new Employee();
}
#Bean
#Scope("singleton")
public Department department(){
return new Department();
}
Case C: Prototype bean inside a singleton bean as dependancy with proxymode defined
#Bean
#Scope("prototype",proxyMode= ScopedProxyMode.TARGET_CLASS)
public Employee employee(){
return new Employee();
}
#Bean
#Scope("singleton")
public Department department(){
return new Department();
}
Guys questions here are:
How will case A, case B and case C work?
I am trying to understand what exactly will be correct way.
Also not specifying proxymode is correct or not?
What happens when proxyMode is not set? how does prototype work then?
What I typically saw in implementation examples on internet is people often do not configure proxyMode either mistakenly or are not aware about this option or maybe they are right.
Thank you for your valuable time.
A, B, and C will all return new instance of Employee when requested.
A and B are usual ways to use prototype scopes.
Not specifying is the usual way. Though in some instances where scope is RequestScope or Session scope, etc, it might make sense to specify proxyMode. Regarding specifying proxyMode, see the last paragraph.
If not set, you get the expected behavior. That is, you get new instance every time a bean instance is requested.
The prototype scope instructs Spring to instantiate a new instance of the bean everytime a bean instance is requested by the application.
You should consider using prototype scope in the following scenarios:
If you have a bean that has a lot of writable state, you may find that the cost of synchronization is greater than the cost of creating a new instance to handle each request from a dependent object.
Some dependent objects need a bean that has private state so that they can conduct their processing separately from other objects that depend on the bean. In this case, singletons are clearly not suitable. Consider prototypes.
It is a good practice that your beans should implement some interface. In that case, Spring uses JDK proxy mechanism to create proxy of your class. But implementing interface is not a requirement. If no interface is implemented by your bean, then Spring uses CGLIB library to create proxy of your bean (unless a class is annotated with #Configuration in which case a different proxy mechanism is used).
By specifying proxyMode=ScopedProxyMode.TARGET_CLASS, you are forcing Spring to use CGLIB proxy mechanism. In the end, just providing #Scope("prototype") is sufficient.
On a side note, know that if you have any methods that hook into lifecycle of a bean (like #PreDestroy, implementing DisposableBean interface, or destroyMethod as a flag in #Bean), then those methods will never be called in prototype scoped beans.
I noticed that the #PreDestroy hooks of my prototype scoped Spring beans were not getting executed.
I have since read here that this is actually by design. The Spring container will destroy singleton beans but will not destroy prototype beans. It is unclear to me why. If the Spring container will create my prototype bean and execute its #PostConstruct hook, why will it not destroy my bean as well, when the container is closed? Once my Spring container has been closed, does it even make sense to continue using any of its beans? I cannot see a scenario where you would want to close a container before you have finished with its beans. Is it even possible to continue using a prototype Spring bean after its container has been closed?
The above describes the puzzling background to my primary question which is: If the Spring container is not destroying prototype beans, does that mean a memory leak could occur? Or will the prototype bean get garbage-collected at some point?
The Spring documentations states:
The client code must clean up prototype-scoped objects and release
expensive resources that the prototype bean(s) are holding. To get the
Spring container to release resources held by prototype-scoped beans,
try using a custom bean post-processor, which holds a reference to
beans that need to be cleaned up.
What does that mean? The text suggests to me that I, as the programmer am responsible for explicitly (manually) destroying my prototype beans. Is this correct? If so, how do I do that?
For the benefit of others, I will present below what I have gathered from my investigations:
As long as the prototype bean does not itself hold a reference to another resource such as a database connection or a session object, it will get garbage collected as soon as all references to the object have been removed or the object goes out of scope. It is therefore usually not necessary to explicitly destroy a prototype bean.
However, in the case where a memory leak may occur as described above, prototype beans can be destroyed by creating a singleton bean post-processor whose destruction method explicitly calls the destruction hooks of your prototype beans. Because the post-processor is itself of singleton scope, its destruction hook will get invoked by Spring:
Create a bean post processor to handle the destruction of all your prototype beans. This is necessary because Spring does not destroy prototype beans and so any #PreDestroy hooks in your code will never get called by the container.
Implement the following interfaces:
1.BeanFactoryAware
This interface provides a callback method which receives a Beanfactory object. This BeanFactory object is used in the post-processor class to identify all prototype beans via its BeanFactory.isPrototype(String beanName) method.
2. DisposableBean
This interface provides a Destroy() callback method invoked by the Spring container. We will call the Destroy() methods of all our prototype beans from within this method.
3. BeanPostProcessor
Implementing this interface provides access to post-process callbacks from within which, we prepare an internal List<> of all prototype objects instantiated by the Spring container. We will later loop through this List<> to destroy each of our prototype beans.
3. Finally implement the DisposableBean interface in each of your prototype beans, providing the Destroy() method required by this contract.
To illustrate this logic, I provide some code below taken from this article:
/**
* Bean PostProcessor that handles destruction of prototype beans
*/
#Component
public class DestroyPrototypeBeansPostProcessor implements BeanPostProcessor, BeanFactoryAware, DisposableBean {
private BeanFactory beanFactory;
private final List<Object> prototypeBeans = new LinkedList<>();
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanFactory.isPrototype(beanName)) {
synchronized (prototypeBeans) {
prototypeBeans.add(bean);
}
}
return bean;
}
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
#Override
public void destroy() throws Exception {
synchronized (prototypeBeans) {
for (Object bean : prototypeBeans) {
if (bean instanceof DisposableBean) {
DisposableBean disposable = (DisposableBean)bean;
try {
disposable.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
prototypeBeans.clear();
}
}
}
Your answer is great. I'd also like to share some notes on an alternative solution that allows prototype members which are natively managed by the Spring IoC container lifecycle through the use of the inner beans.
I recently wrote an answer to a separate question on inner beans. Inner beans are created by assigning bean property values as BeanDefinition objects. Bean definition property values are automatically resolved to (inner) instances (as managed singleton beans) of the bean that they define.
The following XML context configuration element can be used to create distinct autowireable ForkJoinPool beans for each reference which will be managed (#PreDestroy will be called on context shutdown):
<!-- Prototype-scoped bean for creating distinct FJPs within the application -->
<bean id="forkJoinPool" class="org.springframework.beans.factory.support.GenericBeanDefinition" scope="prototype">
<property name="beanClass" value="org.springframework.scheduling.concurrent.ForkJoinPoolFactoryBean" />
</bean>
This behavior is contingent upon the reference being assigned as a property value of a bean definition, though. This means that #Autowired- and constructor-injection do not work with this by default, since these autowiring methods resolve the value immediately rather than using the property value resolution in AbstractAutowireCapableBeanFactory#applyPropertyValues. Autowiring by type will also not work, as type-resolution will not propagate through beans that are BeanDefinitions to find the produced type.
This method will only work if either of the two conditions are true:
The dependent beans are also defined in XML
Or if the autowire mode is set to AutowireCapableBeanFactory#AUTOWIRE_BY_NAME
<!-- Setting bean references through XML -->
<beans ...>
<bean id="myOtherBean" class="com.example.demo.ForkJoinPoolContainer">
<property name="forkJoinPool" ref="forkJoinPool" />
</bean>
</beans>
<!-- Or setting the default autowire mode -->
<beans default-autowire="byName" ...>
...
</beans>
Two additional changes could likely be made to enable constructor-injection and #Autowired-injection.
Constructor-injection:
The bean factory assigns an AutowireCandidateResolver for constructor injection. The default value (ContextAnnotationAutowireCandidateResolver) could be overridden (DefaultListableBeanFactory#setAutowireCandidateResolver) to apply a candidate resolver which seeks eligible beans of type BeanDefinition for injection.
#Autowired-injection:
The AutowiredAnnotationBeanPostProcessor bean post processor directly sets bean values without resolving BeanDefinition inner beans. This post processor could be overridden, or a separate bean post processor could be created to process a custom annotation for managed prototype beans (e.g., #AutowiredManagedPrototype).
In a modular Spring configured application, we use factory beans to provide bean instances across module boundaries.
For example, one module A may expose a bean instance by the name name. Another module B can then consume that bean via a declaration of the style
<bean id="nameBean" class="com.zfabrik.springframework.ComponentFactoryBean">
<property name="componentName" value="A/name" />
<property name="className" value="a.AInterface" />
</bean>
Note that modules have separated class loader hierarchies and the actual implementation class of A/name may not be visible in B. As if in OSGI (although this is NOT OSGi).
My goal is to provide A/name in a programmatic application context in B. However when trying
#Configuration
public static class AppContext {
#Bean AInterface nameBean() {
return lookup("A/name",AInterface.class);
}
}
(lookup does the actual instance retrieval) I see that Spring is trying to configure the returned instance. For example, it will attempt to resolve #Autowired properties of A/names's implementation class - which does not make sense in the context of B (and the deal of the lookup is to provide something fully configured anyway). Even, if I try
#Configuration
public static class AppContext {
#Bean(autowire=Autowire.NO) AInterface nameBean() {
return lookup("A/name",AInterface.class);
}
}
it will go about configuring the returned instance.
How can I provide a bean to the application context without spring touching its implementation instance?
EDIT: As suggested by Sotirios Delimanolis, returning the FactoryBean does AFAICT avoids Spring configuration of the returned instance.
The alternative code would look like this:
#Configuration
public static class AppContext {
#Bean FactoryBean<AInterface> nameBean() {
return new ComponentFactoryBean("A/name",AInterface.class);
}
}
It's not as cool as an #UntouchedBean annotation because of the FactoryBean in the return type, but it solves the problem.
#Sotirios: Please suggest as answer so that I can tag your suggestion accordingly.
/EDIT
Ok, just so it can be closed. The suggested and accepted answer is to return the factory bean.
I am asking this Question in reference to my question:
spring singleton scope
Spring singleton is defined in reference manual as per container per bean.
per container means if we do like:
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml")
MyBean myobj=(MyBean)context.getBean("myBean"); //myBean is of singleton scope.
MyBean myobj1=(MyBean)context.getBean("myBean");
Beans.xml:
<bean id="myBean" class="MyBean"/>
Then myobj==myobj1 will come out to true.Means both pointing to same instance.
For per bean part of phrase per container per bean i was somewhat confused. Am i right in following for per bean :
If we do like
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml")
MyBean myobj=(MyBean)context.getBean("myBean");
MyBean myobj1=(MyBean)context.getBean("mySecondBean");
Beans.xml:
<bean id="myBean" class="MyBean"/>
<bean id="mySecondBean" class="MyBean"/>
Then myobj==myobj1 will come out to false. Means then they are two different instances?
That is correct.
If it helps, you can also think of Spring beans as Instances that you would've otherwise created manually in your Java code using the constructor.
By defining the bean in the Spring XML file, that bean (Instance) gets registered with Spring's App Context and then that instance can be passed around to the other areas of the code.
By creating a new bean, you are effectively creating a new instance. So potentially you could create any number of beans (Instances) of the same class
myBean is a Spring singleton in the sense of every call to beans.getBean("myBean") will allways return the same instance. And mySecondBeanhaving a different id is another Spring singleton. You can have different singleton beans of same class in the same ApplicationContext .
Yes, you're right. Testing it would have told you.
For using spring request scope bean is this definition correct?
<bean id="shoppingCart" class="ShoppingCart" scope="request">
<!-- This requires CGLIB -->
<aop:scoped-proxy/>
</bean>
I modified this from a session scope bean example, and changed only the scope definition, not sure about the proxy thing
I took this example from this link, you can see the full xml:
http://wheelersoftware.com/articles/spring-session-scoped-beans-2.html
Generally - yes, it's correct.
If for every request You'd retrieve the request scoped bean directly from the BeanFactory, then You don't need the proxy.
But You need the proxy if You're going to use the request soped bean as a depenedncy to singleton scoped bean, for example like this:
#Controller
public class MyController {
#Autowired
private ShoppingCart shoppingCart;
}
See this reference page for more details about scoped beans.
As a side note I'd advise to use standard JDK interface-based poxies instead of CGLIB whenever possible. More about proxying with spring can be found in documentation.