In the last two articles, we have basically analyzed the application examples of XmlBeanFactory. In this chapter, let's analyze ApplicationContext. Big guy skip
The first two articles have finished the basic XmlBeanFactory operation examples. Let's talk about ApplicationContext here. As mentioned before, the basic processes of these two things should be similar. For example, we speculated before:
- Read configuration file
- Find the corresponding class according to the configuration file and instantiate it through reflection
- Then it is stored in the container and taken out when called
The difference between ApplicationContext and XmlBeanFactory
Can these speculations still be used in the source code analysis of ApplicationContext? The answer is yes. We talked about the design and implementation of IOC container before, which is nothing more than two series, a BeanFactory and an ApplicationContext. So what kind of XmlBeanFactory do we see before? Let's take a look at the class diagram of XmlBeanFactory
The inheritance system of XmlBeanFactory is XmlBeanFactory - > defaultlistablebeanfactory - > abstractautowirecapablebeanfactory - > abstractbeanfactory - > factorybeanregistrysupport - > defaultsingletonbeanregistry - > simpleliasregistry - > alias registry
But please note: XmlBeanFactory is extended on the basis of DefaultListableBeanFactory. In fact, the BeanFactory interface is finally implemented. Our ApplicationContext is an advanced form of container. Application context adds many other features to a simple container. Why do you say that? Let's take a look at the class diagram of ApplicationContext.
It is not difficult to find that ApplicationContext also implements BeanFactory, but it can be seen here that ApplicationContext has more support.
BeanFactory
BeanFactory is the core of Spring. Many interview questions ask what Spring is? In fact, you can directly answer: Spring is actually a huge package of BeanFactory. Of course, it seems a little one-sided. BeanFactory is indeed the core content of Spring.
BeanFactory provides the most basic IOC container functions. For these functions, we can read its source code
String FACTORY_BEAN_PREFIX = "&"; /** * Get bean by name */ Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; /** * Include bean s */ boolean containsBean(String name); /** * Query whether the bean is of Singleton type */ boolean isSingleton(String name) throws NoSuchBeanDefinitionException; /** * Query whether the bean is of Prototype type */ boolean isPrototype(String name) throws NoSuchBeanDefinitionException; /** * Query whether the class type of the bean is a specific class type */ boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException; /** * class type of query bean */ Class<?> getType(String name) throws NoSuchBeanDefinitionException; /** * Query all aliases of the bean */ String[] getAliases(String name);
In fact, it doesn't have much code, but it provides specifications for using IOC containers. Understanding these helps us understand ApplicationContext. We can directly think that BeanFactory is a simple container form, while ApplicationContext is an advanced container form.
Here, in fact, we have seen some differences between XmlBeanFactory and ApplicationContext. But it's not so obvious here. We might as well take another look at the ApplicationContext. Its implementation class ClassPathXmlApplicationContext is used in our code. What is the difference between its source code and XmlBeanFactory
ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); this.setConfigLocations(configLocations); if (refresh) { this.refresh(); } }
Its initialization is constantly calling super(parent), but the refresh() method completes the initialization of the container.
The implementation code of refresh() method is as follows
public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); // preparation ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // The ultimate purpose of obtaining ConfigurableListableBeanFactory is DefaultListableBeanFactory this.prepareBeanFactory(beanFactory); // Prepare bean factory try { this.postProcessBeanFactory(beanFactory); // An empty implementation. Note that the spring version number here is 5.3x this.invokeBeanFactoryPostProcessors(beanFactory); // Registered bean factory this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); // Spring extracts the BeanPostProcessor from all @ Bean definitions, then registers it in beanPostProcessors, and waits for the subsequent sequential calls to register the BeanPostProcessor this.initApplicationEventMulticaster(); // Initialize event listening multiplexer this.onRefresh(); // An empty implementation this.registerListeners(); // Register listener this.finishBeanFactoryInitialization(beanFactory); // At the most complex step of the spring loading process, start instantiating all BDS this.finishRefresh();// Refresh completed work } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }
On the whole, the method is relatively clear. It highly summarizes what refresh() has done with several major methods. We will explain these processes in detail later. Here is only a summary.
Here, we see a process of ClassPathXmlApplicationContext, which is quite different from our XmlBeanFactory. In our previous speculation, he should load xml first. In fact, it is also done here, but it is hidden deeply. In the specific content of the second part of this loading process, we will post the core code here
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.refreshBeanFactory(); this.loadBeanDefinitions(beanFactory); protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); this.initBeanDefinitionReader(beanDefinitionReader); this.loadBeanDefinitions(beanDefinitionReader); }
In fact, bean initialization and container initialization are all presented in this process. We will talk about this later. However, from the content we summarized, it is not very different from our speculation, but there are a lot of other things. These extra things are exactly the difference between our two container implementations.
Summary:
- The basic implementation of BeanFactory provides a basic IOC container. ApplicaitonContext appears in an advanced form and adds many additional functions.
- XmlBeanFactory is one of the most basic applications of BeanFactory
- XmlBeanFactory and ClassPathXmlApplicationContext both have the processes we speculate, but the implementation is different, and the specific processes are very different