乐趣区

关于java:Spring源码之六onRefresh方法

Spring 源码之六 -onRefresh() 办法

大家好,我是程序员田同学。

明天带大家解读 Spirng 源码之六的 onRefresh() 办法,这是 refresh() 的其中的一个办法,看似是一个空办法,实则他是十分十分重要的,对于进步 Spring 的扩展性。

老规矩,先贴上 Spring 的外围办法 refresh() 办法的源码,以便读者能够丝滑入戏。

@Override
    public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //1、刷新前的筹备
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            //2、将会初始化 BeanFactory、加载 Bean、注册 Bean
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            //3、设置 BeanFactory 的类加载器,增加几个 BeanPostProcessor,手动注册几个非凡的 bean
            prepareBeanFactory(beanFactory);

            try {
                //4、模板办法
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                // 执行 BeanFactory 后置处理器
                invokeBeanFactoryPostProcessors(beanFactory);

                // 5、Register bean processors that intercept bean creation.
                // 注册 bean 后置处理器
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                // 国际化
                initMessageSource();

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

                // Initialize other special beans in specific context subclasses.
                //6、模板办法 --springboot 实现了这个办法
                onRefresh();

                // Check for listener beans and register them.
                //7、注册监听器
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //8、实现 bean 工厂的初始化 ** 办法 **********************************************
                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() 是模板办法,具体的子类能够在这里初始化一些非凡的 Bean(在初始化 singleton beans 之前)

这是 onRefresh() 的次要作用,那么文章到这里就完结了,感激浏览!

开玩笑,只说作用不举例那和耍流氓没有什么区别,接下来就以 Spirng 的典型实现 Springboot 来举例。

该办法的执行机会是 Spring 曾经加载好了一些非凡的 bean(内置的一些 bean,实现了 bean 工厂后置处理器的类)之后,在实例化单例 bean 之前。让咱们来看 Springboot 是怎么调用这个模板办法的。

一路的点击 Springboot 的外围入口 run() 办法,一路找到了咱们明天的配角,Spring 的 refresh() 办法中的 onRefresh() 办法。

点击查看 Springboot 的 onRresh() 的实现办法。

有两个包门路含有 boot 的,肯定就是 Spirngboot 的实现办法。

这是 Spirng 的 onRresh() 的实现办法。

比对一下 Spirng 的 onRresh() 和 SpirngbootRefersh 的实现类比照,Springboot 多了两个实现类,ReactiveWebServerApplicationContext 类和 ServletWebServerApplicationContext 类。

咱们别离查看这两个实现的 onRresh() 办法都做了什么?

办法名都是 createWebServer() 办法,认为这两个办法都是一个办法,认真一看发现并不是。

两个 createWebServer() 办法做了什么呢?咱们 debug 进去搂一眼。

ReactiveWebServerApplicationContext 类的 onRresh() 办法并没有执行到,见名知意应该是跟 webServer 治理相干的,限于篇幅问题,留个坑临时放在吧。

ServletWebServerApplicationContext 类的 onRefresh() 办法执行到了,咱们进去一探到底。

    private void createWebServer() {
        WebServer webServer = this.webServer;
        ServletContext servletContext = getServletContext();
        // 第一次进来 webServer servletContext 都是 null, 会进到 if 分支外面
        if (webServer == null && servletContext == null) {// 这里就会来查找 ServletWebServerFactory,也就是 web 容器的工厂, 具体看下 getWebServerFactory() 办法,// 还是 ServletWebServerApplicationContext 这个类的办法
            // 创立了 TomcatServletWebServerFactory 类
            ServletWebServerFactory factory = getWebServerFactory();
            // 创立 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();}

外围应该是 factory.getWebServer(getSelfInitializer()),这个办法是创立了一个容器。都有哪些容器呢?

咱们看一下他的实现类有 Jetty、Mock、Tomcat*,Tomcat 就不用提了,Jetty 略有耳闻和 Tomcat 并列的容易。

那 mock 是什么呢,带着求知的态度百度一下,没看懂,过!

咱们还是重点看 Tomcat。进去看 TomcatServletWebServerFactory 的实现类,new 了一个 Tomcat 的对象,并做了一些 Tomcat 的设置,什么协定、端口 …… 等等。

@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {if (this.disableMBeanRegistry) {Registry.disableRegistry();
   }
   // 创立 Tomcat
   Tomcat tomcat = new Tomcat();
   File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
   tomcat.setBaseDir(baseDir.getAbsolutePath());
   // 同步非阻塞 io 协定
   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);
   // 这里会创立 TomcatWebServer 实例, 并返回
   return getTomcatWebServer(tomcat);
}

好了,到此就把 spirng 的模板办法 onRefresh() 在 Springboot 中是怎么用的说说分明了,顺道把 Tomcat 是怎么内嵌到 Springboot 中简要的解说了一下。

貌似有点跑题了,讲 onRefresh() 办法呢,后果在 springboot 中饶了一大圈。不过,能让读者更好的了解 Spirng 和 Springboot 的关系,能认真的读读也是大有裨益的。

也是真的感叹 Spirng 作者们的功力之强,Spirng 的扩展性有多少的弱小。

退出移动版