I am confused about the lifecycle of Spring.
XmlBeanFactory beanFactory
= new XmlBeanFactory(new ClassPathResource("SpringHelloWorld.xml"));
Whether the above snippet of codes creates the object or not?
If the above answer is true.
a) Then, for the bean where scope is "singleton" get the object which was created during the above snippet of code. Am i right or wrong?
b) For the case where scope is "prototype", whether the created object was unused. Because, the container always return new object.
XmlBeanFactory beanFactory
= new XmlBeanFactory(new ClassPathResource("SpringHelloWorld.xml"));
Whether the above snippet of codes creates the object or not?
If the answer is false,
How the spring framework validates whether the bean definition is correct or not.
From the answer of Henry
Usually, singleton beans are created when the context starts. This can be changed with the lazy-init or default-lazy-init attributes.
Prototype beans are only created when needed.
Only syntactically, there might still be errors when the bean is instantiated, for example if a required property is not provided.
BeanFactory does not pre-instantiate singletons on startup like ApplicationContext does. So even if your bean is non-lazy and singleton, it won't be created.
prototype beans are created on demand, every time you ask for a prototype bean you'll get a new instance. But once such bean was used during autowiring, the same instance will be used forever.
With ApplicationContext all singletons are created eagerly and prototype beans only on demand.
See also
BeanFactory vs ApplicationContext
Usually, singleton beans are created when the context starts. This can be changed with the lazy-init or default-lazy-init attributes.
Prototype beans are only created when needed.
Related
I am now learning little bit detail about Spring IoC Containers with the difference between BeanFactory Vs Application Context. I was also referring the previous stack overflow discussion and tutorial point from the following links,
BeanFactory vs ApplicationContext
https://www.tutorialspoint.com/spring/spring_ioc_containers.htm
In my learning I found that ApplicationContext is capable of resolving textual messages from a properties file and the ability to publish application events to interested event listeners
And BeanPostProcessor Registration and BeanFactoryPostProcessor Registration doing manually in BeanFactory and automatically doing in application context,
So my confusions are,
Since BeanFactory Manually doing BeanPostProcessor registration, Does that mean the developer is doing something while bean is getting initiating ? Because, the same process ApplicationContext does automaticall according to documentations
What is the purpose of BeanFactoryPostProcessor registration ? What is the difference between BeanPostProcessor and BeanFactoryPostProcessor ?
If we say ApplicationContext has the ability to resolving text messages from properties file (Message source access), So for what purpose application context is communicating with property file ?
How can I better understand this concept ?
BeanFactory is lightweight and it doesn't load in-memory/initialize any bean from application.xml (even singleton beans) unless factory.getBean("bean-name") method is called; whereas ApplicationContext is heavyweight is loads everything on container startup. BeanFactory also supports limited scopes like proto and singleton and features like AOP doesn't work with BeanFactory.
So to answer your 1st question YES while using BeanFactory just loading the xml and creating BeanFactory object does not guarantee any bean is initialized; only place to use it is when you are concerned of runtime memory consumption
Note: ApplicationContext extends ListableBeanFactory extends BeanFactory.
BeanPostProcessor as the name suggest gives you hooks to work on an instance of a bean created by the spring container by ApplciationContext/BeanFactory implementation (i.e. before and after initialization) Spring AOPs like transactions. caching etc. ref #Required for example. BeanFactoryPostProcessor on the other end lets you modify the actual bean definition before initialization of the instance. The PropertyResourceConfigurer and PropertyPlaceholderConfigurer are two good examples refer PropertyResourceConfigurer example, how properties are changed before initializing the actual beans.
ApplicationContext main responsibility is initialization of bean, now based on the individual bean is defined it provides way to perform specialized tasks like resources bundle loading/property configurer. I suggest you look at the javadoc for a concrete implementation of ApplicationContext like GenericApplicationContext . If you look at how each methods are implemented you will understand how the control flows from AppContext to individual beans before and after they are initialized. AppContext only has the contract for supports tasks
I have been trying to understand spring beans. As per my understanding, by default all beans are singleton and a singleton bean with lazy-init property set to true is created when it is first requested and singleton bean with lazy-init property set to false is created when the application context is created.
So, in an application, when a user request comes in ( where each request is a separate thread), do all these threads share the same singleton beans when requested within the program/class?
Yes, if the bean is created with default scope, the bean is shared across threads. However, another scope can be used to achieve the behaviour you mentioned.
See: https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch04s04.html?
Yes, by default (scope == 'singleton'), all threads will share the same singleton bean. There are two other bean scopes, session and request, that may be what you're looking for. The request scope creates a bean instance for a single HTTP request while session scope maintains a unique bean for each HTTP Session.
For a list and description of all of the Spring bean scopes, check out: Spring bean scopes
The best way to understand this is to understand how #Autowired annotation works.
Or in other words to understand "Spring Dependency Injection".
You said, "
by default all beans are singleton
We use #Autowired when injecting one layer into another between two layers.
If exemplify: Suppose, I want to inject UserService UserController. UserService is a Singleton bean. Creates an instance from UserService and Stores its cache. When we want to inject this service with #Autowired annotation. This annotation brings the UserService stored in the cache.
In this way, Even if we do this inject operation in many classes.#Autowired inject an instance of UserService with singleton bean instead of dealing with one UserService at each time. It saves us a big burden.
This is the fundamental working logic of Spring Singleton Bean.
Also, Spring Ioc Container manages this whole process.
Class Student Depends on class Result
<bean id = "result" lazy-init = "false">
</bean>
<bean id = "student" lazy-init = "true">
</bean>
Result: result bean will be loaded at container start-up and student will be loaded when we call getBean method.
<bean id = "result" lazy-init = "false" scope = "prototype">
</bean>
<bean id = "student" lazy-init = "true" scope = "Singleton">
</bean>
Result: No bean will be loaded at container start-up.
Question: Why scope is affecting class load; what does scope have to do with class load time?
According to documentation
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. That is, the bean is injected into another bean or you
request it through a getBean() method call on the container. As a
rule, use the prototype scope for all stateful beans and the singleton
scope for stateless beans.
Since you didn't yet call getBean or inject it to another bean, this bean is not been created.
By the way, even when you declared your singletone bean as lazy-init="true", it will be created, if you'll inject it (for example with #Autowired annotation) to other non-lazy bean.
A bean of scope singleton is a bean that is created once per application context. A bean of scope prototype is a bean that is instantiated every time.
In other words if your have two classes that autowire a singleton scoped bean, all instances of those two classes will reference the same single instance of the bean. Doing the same with autowiring a prototype scoped bean will create a new instance for each instance that is autowired.
The property for lazy-init defines when the bean is instantiated: As a prototype scoped bean is instantiated each time there is no difference if the property is set to true or false, because the bean is instanciated when it is used (either by being autowired or by programmatic retrieval from the context). For a singleton scoped bean however it does make a difference:
If lazy-init is set to false (which is the default), the bean is instantiated on startup.
If the property is set to true, the bean is instantiated on the first use (through autowiring or programmatic retrieval from the context).
Defining a lazy load singleton bean may come in handy in cases where the bean may be costly to create and may only be used in special cases, the the application may actually run without ever calling any method on that bean.
Take a look at the Spring IoC container documentation, which goes into great detail.
I would like to put the theory in a simple manner which will help you understand better,
Only Singleton beans are eager loaded | prototype beans are lazily loaded(every req or indirect references)
If singleton bean is defined as lazy-init=true (by-default its false) then bean will be instantiated on first usage(using getBean or any indirect reference)
But for prototype bean lazy-init does not make any diff if making lazy-init=true or false as it will be lazily loaded always
You can try using #PostConstruct to play around different combinations in spring bean injections to know when beans are getting instantiated.
I've read that dynamic bean definition change. I try it in a simple code example (see code below), and I find it very attractive in situations where I don't want to stop server but add/change bean definition.
Questions:
Is it safe do to so (see code below)?
I've read that it is possible to achieve bean definition change in runtime with help of StaticApplicationContex or BeanPostProcessor or BeanFactoryPostProcessor? So what is the difference?
public class Main {
final static String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<beans xmlns=\"http://www.springframework.org/schema/beans\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xmlns:context=\"http://www.springframework.org/schema/context\"\n" +
" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n" +
" <context:annotation-config />\n" +
" <context:component-scan base-package=\"vbah\"/>";
final static String contextA =
"<bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextA\"/>\n" +
"</bean></beans>";
final static String contextB =
"<bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextB\"/>\n" +
"</bean></beans>";
public static void main(String[] args) throws IOException {
//create a single context file
final File contextFile = new File("src/resources/spring-config.xml");
//write the first context into it
FileUtils.writeStringToFile(contextFile, header + contextA);
//create a spring context
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
new String[]{contextFile.getPath()}
);
//echo "fromContextA"
System.out.println(context.getBean("test"));
//write the second context into it
FileUtils.writeStringToFile(contextFile, header + contextB);
//refresh the context
context.refresh();
//echo "fromContextB"
System.out.println(context.getBean("test"));
}
}
EDIT:
Can you answer the questions below:
As I understand BeanPostProcess allow you to modify already existed bean instances at runtime by wrapping the object with proxy. Am I right?
AbstractApplicationContext#refresh() drop all singleton beans and recreate them.
But If I want to change the definition of prototype/custom scoped bean?
If I've got two beans: A and B. A has reference to B. If I change the bean definition in such way that it doesn't contain definition of B. Than B instances will be destroyed, but new instances won't be created. Than A will get a null dependency. Am I right?
StaticApplicationContext and BeanFactoryPostProcessor both allow me to change a bean definition in runtime. But what are the difference, pros/cons?
[Main question] Why Spring has 3 mechanism to achieve the same goal. Can you make a brief compoarison (or usecases examples) between AbstractApplicationContext#refresh(), StaticApplicationContext and BeanFactoryPostProcessor please.
Is it safe do to so (see code below)?
You'll have to define safe.
The AbstractApplicationContext#refresh() method javadoc states
As this is a startup method, it should destroy already created
singletons if it fails, to avoid dangling resources. In other words,
after invocation of that method, either all or no singletons at all
should be instantiated.
Basically every bean in your context will be destroyed and all references to them will be dropped, making them candidates for garbage collection. You need to make sure that those beans have appropriate ways to release any resources they might have. There are different ways to do that
Make your class implement the DisposableBean interface.
Add a destroy-method attribute to your <bean> or #Bean definition.
Annotate a method with #PreDestroy.
Note that refresh() will typically eagerly refresh your ApplicationContext, ie. re-instantiate all the beans immediately. You may notice some slow down in your application while that happens.
I've read that it is possible to achieve bean definition change in
runtime with help of StaticApplicationContext or BeanPostProcessor or
BeanFactoryPostProcessor? So what is the difference?
StaticApplicationContext is one of the ApplicationContext classes where you register the bean definitions yourself. In your example, the bean definitions are parsed from your XML file and registered behind the scenes. With StaticApplicationContext, you use registerBeanDefinition(..) or the other registerXxx() methods to explicitly register a bean definition.
A BeanFactoryPostProcessor has access to the BeanFactory being used and therefore all the bean definitions that have been registered. As such, you can retrieve any BeanDefinition you want and modify it. As the javadoc for BeanFactoryPostProcess#postProcessBeanFactory(..) states
All bean definitions will have been loaded, but no beans will have
been instantiated yet. This allows for overriding or adding properties
even to eager-initializing beans.
You can change the bean definition before the ApplicationContext actually uses it.
Finally, a BeanPostProcessor doesn't change the bean definition. You can use a BeanPostProcessor to change how a bean is created but the underlying BeanDefinition will stay the same.
For your edit (which is bigger than the actual answer :) )
As I understand BeanPostProcess allow you to modify already existed
bean instances at runtime by wrapping the object with proxy. Am I
right?
It's not just for proxying, you can do anything you want with the object: modify its properties, register it in some other context, make it null, etc. This goes around the bean definition.
AbstractApplicationContext#refresh() drop all singleton beans and
recreate them.
But If I want to change the definition of prototype/custom scoped
bean? If I've got two beans: A and B. A has reference to B. If I
change the bean definition in such way that it doesn't contain
definition of B. Than B instances will be destroyed, but new instances
won't be created. Than A will get a null dependency. Am I right?
In an ApplicationContext, you declare your bean definitions. If you're going to change a bean definition, change it in a BeanFactoryPostProcessor or declare it differently in the context configuration.
For dependencies, if you destroy the B bean definition, there won't be a bean to inject into A and Spring will complain, throwing NoSuchBeanDefinitionException. Bean injection never injects null unless you explicitly tell it to.
StaticApplicationContext and BeanFactoryPostProcessor both allow me to
change a bean definition in runtime. But what are the difference,
pros/cons?
The two serve completely different purposes. StaticApplicationContext is an ApplicationContext implementation. Here, you declare bean definitions. A BeanFactoryPostProcessor serves to modify those bean definitions in any way, based on whatever condition you care to implement.
Why Spring has 3 mechanism to achieve the same goal. Can you make a
brief comparison (or usecases examples) between
AbstractApplicationContext#refresh(), StaticApplicationContext and
BeanFactoryPostProcessor please.
The goal is not the same. An ApplicationContext is different than a BeanFactoryPostProcessor and comes into play at a different time in the context life cycle (see that nice graph you had in a previous question).
I don't have use cases for you. Learn what each of the above can do and you'll know when to apply them when you get specific requirements.
In an imported spring context XML file I define a bean instance that implements BeanPostProcessor.
In the importing spring context I define a number of beans (using BeanDefinitionBuilder in a custom BeanDefinitionParser).
Not all defined beans are given to the postProcessBeforeInitialization() method on my BeanPostProcessor.
It seems that some other FactoryBeans somehow affect this situation. When looking in the ApplicationContext instance with a debugger I can see all my beans inside - also the ones not being given to the BeanPostProcessor.
How can this happen?