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的设置,什么协定、端口......等等。

@Overridepublic 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的扩展性有多少的弱小。