spring source code refresh Part 2
Hello, I'm a classmate of programmer Tian
The previous article gave an overall interpretation of the spring core startup method refresh, but only in general. Next, a systematic article will be published to deeply interpret the source code of each method.
For the first article, see Method overview of spring source code
First, the first method is the prepareRefresh() method, which is very simple and is not the focus of this article. This method records the start time of the container and initializes the listening container.
protected void prepareRefresh() { // Switch to active //Record start time this.startupDate = System.currentTimeMillis(); System.out.println("spring Start time is--------------------" + this.startupDate); this.closed.set(false); System.out.println("spring Mark as not closed--------------------" + this.closed); this.active.set(true); System.out.println("spring Current active state--------------------" + this.active); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } // Initialize any placeholder property sources in the context environment. //Empty method initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties //Validate xml configuration file getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... //Initialize the applicationlisters listening container if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<> (this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); }
Readers can take a general look at this method and quickly grasp it as a whole.
The next is today's highlight - the obtainFreshBeanFactory() method, which is the second method in the refresh() method and one of the core methods in the whole refresh() method.
The main function of this method is to initialize BeanFactory, load beans, register beans, etc. (Bean did not complete initialization)
Click in the obtainFreshBeanFactory() method to find out.
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // Close the old BeanFactory (if any), create a new BeanFactory, load Bean definitions, register beans, and so on refreshBeanFactory(); // Return to the BeanFactory you just created ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
refreshBeanFactory() should be the highlight of this method. Let's go deeper.
@Override protected final void refreshBeanFactory() throws BeansException { // If BeanFactory has been loaded in ApplicationContext, destroy all beans and close BeanFactory // Note that there can be more than one BeanFactory in an application. This does not mean whether there is a BeanFactory in the global application, but whether there is a BeanFactory in the current ApplicationContext if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // Initialize a DefaultListableBeanFactory. Why use this BeanFactory? Because this is the best BeanFactory. DefaultListableBeanFactory beanFactory = createBeanFactory(); // Serialization for BeanFactory beanFactory.setSerializationId(getId()); // Set two configuration properties of BeanFactory: whether to allow Bean overwrite and whether to allow circular reference customizeBeanFactory(beanFactory); // Load beans into BeanFactory loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
Simply put, why is DefaultListableBeanFactory the best BeanFactory? You can see the inheritance diagram.
// Set two configuration properties of BeanFactory: whether to allow Bean overwrite and whether to allow circular reference customizeBeanFactory(beanFactory);
This method is just a setting to set whether circular dependency is allowed. What is circular dependency? That is, they are interdependent between A-B-C. spring has its own mechanism to deal with circular dependency. For analysis in future articles, this step is only to configure whether circular dependency is allowed. Readers can know it clearly.
// This method will load each Bean according to the configuration, and then put it into the BeanFactory loadBeanDefinitions(beanFactory);
After the above series of steps, a beandefinition is formed. Beandefinition is what we often call a bean, that is, an enhanced version of an object.
Next, you need to add the bean to the beanfactory. This step is left to the loadBeanDefinitions() method.
spring method naming is really exquisite. Just look at the method name and probably know what each method does!
Create a bean definition reader (bean reader) to read beans in xml. Although xml is rarely used, it is classic to use it as an example.
The real work is loadbean definitions (bean definition reader). It's a long way down. Parse the bean in our xml into BeanDefinition, and call the registerBeanDefinition() method to register it in the registry and send registration events.
To sum up, the Bean container has been initialized here, and the < Bean / > configuration has been transformed into beandefinitions accordingly. Then, each BeanDefinition has been registered to the registry, and the registration event has been sent.
At this point, the obtainFreshBeanFactory() method officially ends.
spring's calling process link is very, very long. You get lost after clicking in step by step. Tian believes that a better way is to stand outside the method to see what the method does, and then gradually split it into each method.
Stand outside refresh() and look at the two methods. prepareRefresh() prepares for the refresh. obtainFreshBeanFactory() registers the bean and adds it to beanfactory.
Well, that's all for today's spring source code analysis.