Spring source code 6 - onRefresh() method

Posted by joshuamd3 on Sat, 05 Mar 2022 03:46:47 +0100

Spring source code 6 - onRefresh() method

Hello, I'm classmate Tian, a programmer.

Today, I will take you to interpret onRefresh() method of Spirng source code 6. This is one of the methods of refresh(). It seems to be an empty method, but in fact it is very, very important to improve the scalability of Spring.

As the old rule, first paste the source code of Spring's core method refresh() method, so that readers can slide into the play.

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //1. Preparation before refresh
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            //2. Bean factory will be initialized, beans will be loaded, and beans will be registered
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            //3. Set the class loader of BeanFactory, add several beanpostprocessors, and manually register several special beans
            prepareBeanFactory(beanFactory);

            try {
                //4. Template method
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //Execute BeanFactory post processor
                invokeBeanFactoryPostProcessors(beanFactory);

                // 5,Register bean processors that intercept bean creation.
                //Register bean post processor
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                //internationalization
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //6. Template method -- springboot implements this method
                onRefresh();

                // Check for listener beans and register them.
                //7. Register listener
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //8. Complete the initialization * * method of bean factory**********************************************
                finishBeanFactoryInitialization(beanFactory);

                //9, Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }
onRefresh()It is a template method. Specific subclasses can initialize some special methods here Bean(In initialization singleton beans (before)

This is the main function of onRefresh(), so the article is over here. Thank you for reading!

I'm kidding. It's no different from playing hooligans. Next, take Springboot, a typical implementation of Spirng, as an example.

The execution time of this method is after Spring has loaded some special beans (some built-in beans and classes that implement the post processor of the bean factory) and before instantiating the singleton bean. Let's see how Springboot calls this template method.

Click the run() method of the core entry of Springboot all the way, and find our protagonist today, onRefresh() method in Spring's refresh() method.

Click to view the implementation method of onRresh() of Springboot.

There are two package paths containing boot, which must be the implementation method of Spirngboot.

This is the implementation method of Spirng's onRresh().

Compare the implementation classes of Spirng's onRresh() and spirngbootrefresh. Springboot has two more implementation classes, reactivewebserver ApplicationContext and servletwebserver ApplicationContext.

Let's look at what the onRresh() method of these two implementations do respectively?

The method names are both createWebServer() methods. It is assumed that these two methods are the same method. A closer look shows that they are not.

What do the two createWebServer() methods do? Let's debug in and have a look.

The onresh () method of the reactivewebserver ApplicationContext class has not been implemented. As the name implies, it should be related to webServer management. Due to space constraints, leave a hole for the time being.

The onRefresh() method of servletwebserver ApplicationContext class has been executed. Let's go in and find out.

    private void createWebServer() {
        WebServer webServer = this.webServer;
        ServletContext servletContext = getServletContext();
        //For the first time, the webServer servletContext is null and will enter the if branch
        if (webServer == null && servletContext == null) {
            //Here we will find the ServletWebServerFactory, that is, the factory of the web container. For details, see the getWebServerFactory() method,
            // Or the method of ServletWebServerApplicationContext
            //Created TomcatServletWebServerFactory class
            ServletWebServerFactory factory = getWebServerFactory();
            //Create Tomcat
            this.webServer = factory.getWebServer(getSelfInitializer());
        }
        else if (servletContext != null) {
            try {
                getSelfInitializer().onStartup(servletContext);
            }
            catch (ServletException ex) {
                throw new ApplicationContextException("Cannot initialize servlet context", ex);
            }
        }
        initPropertySources();
    }

The core should be factory Getwebserver (getselfinitializer ()), this method creates a container. What containers are there?

Let's take a look at his implementation classes, such as jetty, Mock and Tomcat *. Tomcat doesn't need to be mentioned. Jetty has heard that it's easy to juxtapose with Tomcat.

What's mock? Baidu, with an attitude of seeking knowledge, didn't understand it, too!

Let's focus on Tomcat. Go in and see the implementation class of TomcatServletWebServerFactory. A Tomcat object is created and some Tomcat settings are made. What protocol and port wait.

@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
   if (this.disableMBeanRegistry) {
      Registry.disableRegistry();
   }
   //Create Tomcat
   Tomcat tomcat = new Tomcat();
   File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
   tomcat.setBaseDir(baseDir.getAbsolutePath());
   // Synchronous non blocking io protocol
   Connector connector = new Connector(this.protocol);
   connector.setThrowOnFailure(true);
   tomcat.getService().addConnector(connector);
   customizeConnector(connector);
   tomcat.setConnector(connector);
   tomcat.getHost().setAutoDeploy(false);
   configureEngine(tomcat.getEngine());
   for (Connector additionalConnector : this.additionalTomcatConnectors) {
      tomcat.getService().addConnector(additionalConnector);
   }
   prepareContext(tomcat.getHost(), initializers);
   //The Tomcat webserver instance will be created and returned
   return getTomcatWebServer(tomcat);
}

Well, now let's explain how the template method onRefresh() of spirng is used in Springboot. By the way, let's briefly explain how Tomcat is embedded in Springboot.

It seems to be a bit off the topic. I talked about onRefresh() method. As a result, I spared a big circle in springboot. However, it can make readers better understand the relationship between Spirng and springboot, and it is also helpful to read it carefully.

It's also true to lament the strength of Spirng authors and how powerful Spirng's scalability is.

Topics: Java Spring Spring Boot Back-end