These reviews
The refresh process of the ApplicationContext is the Bean discovery process, the Bean reading process, and the Bean registration process. Today, let’s analyze the source code further.
Refresh the obtainFreshBeanFactory
Let’s navigate directly to the following line in the Refresh function of AbstractApplication. For those who want to see the previous parsing process, see this article exploring SpringBoot- take a look at the Spring core source code ApplicationContext (8).
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
Copy the code
As you can see from the comments, this way is to tell the subclass to refresh the inner bean Factory,
Let’s go inside the obtainFreshBeanFactory.
/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory(a) {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ":" + beanFactory);
}
return beanFactory;
}
Copy the code
As you can see, the return value beanFactory is obtained by getBeanFacotry. But what about the function call refreshBeanFactory? RefreshBeanFactory is the implementation of Bean discovery, reading, and registration. Let’s move on.
/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */
A specific refresh operation is performed on the bean factory specified by this context.
// If there was a bean Factory before, it is destroyed and a new bean Factory is initialized for the life of the next context
@Override
protected final void refreshBeanFactory(a) throws BeansException {
// Check whether a BeanFactory exists
if (hasBeanFactory()) {
/ / destruction of Beans
destroyBeans();
closeBeanFactory();
}
try {
// Create a BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// Set the serial number to facilitate deserialization
beanFactory.setSerializationId(getId());
/ / custom BeanFacotory
customizeBeanFactory(beanFactory);
/ / found BeanDefinition
loadBeanDefinitions(beanFactory);
// Set beanFactoryMonitor to the created beanFactory
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory; }}catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for "+ getDisplayName(), ex); }}Copy the code
Everything is in the comment, first carefully read the comment. As you can see, the key Bean discovery process here is in loadBeanDefinitions. When you try to look at the implementation, you find that this method is an abstract method, and the concrete implementation class implements it in different ways depending on the source. The way we are XML, see AbstractXmlApplicationContext can directly.
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
// Load bean definitions with XmlBeanDefinitionReader
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// Create an XmlBeanDefinitionReader with the given BeanFactory
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean Definition Reader with the resource loading environment of this context
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
// Allow subclasses to provide specific initializations for readers and then perform the actual load Bean definitions
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
Copy the code
Look at the comments, then go on to loadBeanDefinitions(beanDefinitionReader)
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// Notice that the getConfigResources() method is called
Resource[] configResources = getConfigResources();
if(configResources ! =null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if(configLocations ! =null) { reader.loadBeanDefinitions(configLocations); }}Copy the code
Note here call getConfigResources () method, we in the implementation of the back to have a look at ClassPathApplicationContext. AbstractXmlApplicationContext yes, here is the final call is ClassPathApplicationContext implementation. I’m using the template pattern here, and if you don’t know the template design pattern, I’ll go over it separately.
@Override
protected Resource[] getConfigResources() {
return this.configResources;
}
Copy the code
At this point, you can think of it as the discovery process for refresh’s Bean.
We’ll look at reading and registering beans tomorrow.
About writing
From now on, I will write an article here every day, with no limit on subject matter, content or word count. Try to put your daily thoughts into it.
If this article has helped you, could you please write down which part? Effective feedback helps me the most.
I’m shane. Today is August 14th, 2019. 21st day of the 100-day writing project, 21/100.