About ApplicationContext and BeanFactory
If used ApplicationContext
, the configured beans will be instantiated when the container is loaded if the scope
property is . singleton
The advantage is that it can be preloaded and fast; the disadvantage is that it consumes memory.
If used BeanFactory
, when you instantiate the object, the configured bean will not be instantiated immediately, it will be instantiated when you use it. BeanFacotry
All beans are loaded lazily. The advantage of this is to save memory, the disadvantage is speed.
Generally, there are no special requirements and should be used ApplicationContext
.
ApplicationContext
It is a more advanced container of Spring with very powerful functions:
1. Provide text parsing tools, including support for internationalization
2. Provide a general method for loading file resources, such as pictures.
3. Events can be sent to beans registered as listeners.
ApplicationContext three commonly used implementations:
1.ClassPathXmlApplicationContext: Loaded from the classpath.
2.FileSystemXmlApplicationContext: Loaded from the file system.
3.XmlWebApplicationContext: Loaded from the Web system.
Bean life cycle
When a bean is loaded into the container, its lifecycle begins:
- 1. The container looks for the definition information of the Bean and instantiates it.
When our program loads the beans.xml (or spring-config.xml) file, instantiate our bean (provided that scope=singleton) into memory.
- 2. Using dependency injection, Spring configures all properties of the bean according to the bean definition information.
Use setter methods to set properties, so the Bean class must provide setter methods for properties.
- 3. If the Bean implements the BeanNameAware interface, the factory calls the Bean's setBeanName() method to pass the Bean's ID.
setBeanName(String s)
method to get the ID number of the bean being instantiated.
For example, in the following example, we let the class in the entry [ Spring - Getting Started ] UserService
implement the BeanNameAware
interface, and then rewrite its setBeanName(String s)
methods
package com.gavin.service;
import org.springframework.beans.factory.BeanNameAware;
public class UserService implements BeanNameAware{
private String name;
private ByeService byeService;
public UserService() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ByeService getByeService() {
return byeService;
}
public void setByeService(ByeService byeService) {
this.byeService = byeService;
}
public void sayHello() {
System.out.println("Hello, " + name);
byeService.sayBye();
}
@Override
public void setBeanName(String s) {
System.out.println("当前Bean的ID号为:" + s);
}
}
After running TestMain
the main method at this point, the result is as follows:
As you can see, we UserService
got the ID of the current class in the class, which is exactly the ID we configured in the Spring
configuration file.
- 4. If the Bean implements the BeanFactoryAware interface, the factory calls the setBeanFactory() method to pass in the factory itself.
setBeanFactory(BeanFactory beanFactory)
Methods can pass us the factory itself.
Similarly BeanNameAware
, implementing this interface allows us to get the current factory in the Bean object.
5. If the Bean implements the ApplicationContextAware interface, the factory calls the setApplicationContext() method to pass in the context.
6. If BeanPostProcessor (Bean post processor) is associated with Bean, then their postProcessBeforeInitialization() method is called.
The post-processor BeanPostProcessor is somewhat similar to the Filter in the Web.
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("postProcessBeforeInitialization方法被调用");
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("postProcessAfterInitialization方法被调用");
return o;
}
}
Configuration in beans.xml:
<bean id="myBeanPostProcessory" class="com.gavin.beanlife.MyBeanPostProcessor"/>
Assuming that a post-processor is configured, the postProcessBeforeInitialization
method .
The application requirements of the post-processor are:
- Record when each object was instantiated
- Filter the IP of each calling object
Add an attribute to all objects and get other functions (so-called AOP, aspect-oriented programming, programming for all objects)
7. If the Bean implements the
InitializingBean
interface, the method will be calledafterPropertiesSet()
.
This method will be called before the custom initialization method and the postProcessAfterInitialization() method of the post processor.
- 8. If you customize the init-method yourself, call your own customized initialization method
<bean id="personService" init-method="init" class="com.gavin.beanlife.PersonService">
<property name="name" value="Gavin"/>
</bean>
9. Finally, if there
BeanPostProcessor
are associated beans, theirpostProcessAfterInitialization()
methods are called.10. Use Beans
11. Container close
12. When the container is closed, if the
DisposableBean
interface is implemented, the method will be calleddestroy()
.13. If you customize the destruction method and configure destroy-method, you will call your own customized destruction method . The configuration is as follows:
<bean id="personService" init-method="init" destroy-method="destroy" class="com.gavin.beanlife.PersonService">
<property name="name" value="Gavin"/>
</bean>
[Note] In actual development, all the above steps may not be required. As needed. General steps: 1->2->6->9->10->11
Question: Is the life cycle the same for obtaining Beans through BeanFactory and obtaining Beans through ApplicationContext?
Answer: Not the same, the life cycle of BeanFactory getting Bean is much simpler!
Compare the two pictures below: