Spring源码之六-onRefresh()方法
大家好,我是程序员田同学。
今天带大家解读Spirng源码之六的onRefresh()方法,这是refresh()的其中的一个方法,看似是一个空方法,实则他是非常非常重要的,对于提高Spring的扩展性。
老规矩,先贴上Spring的核心方法refresh()方法的源码,以便读者可以丝滑入戏。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh() ; ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() ; prepareBeanFactory(beanFactory ) ; try { postProcessBeanFactory(beanFactory ) ; invokeBeanFactoryPostProcessors(beanFactory ) ; registerBeanPostProcessors(beanFactory ) ; initMessageSource() ; initApplicationEventMulticaster() ; onRefresh() ; registerListeners() ; finishBeanFactoryInitialization(beanFactory ) ; finishRefresh() ; } catch (BeansException ex) { if (logger.isWarnEnabled() ) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans() ; cancelRefresh(ex ) ; throw ex; } finally { resetCommonCaches() ; } } }
1 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()方法执行到了,我们进去一探究竟。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private void createWebServer () { WebServer webServer = this .webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null ) { ServletWebServerFactory factory = getWebServerFactory(); 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的设置,什么协议、端口……等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override public WebServer getWebServer(ServletContextInitializer... initializers ) { if (this.disableMBeanRegistry) { Registry . disableRegistry() ; } Tomcat tomcat = new Tomcat() ; File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat" ) ; tomcat.setBaseDir(baseDir .getAbsolutePath () ); 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); return getTomcatWebServer(tomcat ) ; }
好了,到此就把spirng的模板方法onRefresh()在Springboot中是怎么用的说说清楚了,顺道把Tomcat是怎么内嵌到Springboot中简要的讲解了一下。
貌似有点跑题了,讲onRefresh()方法呢,结果在springboot中饶了一大圈。不过,能让读者更好的理解Spirng和Springboot的关系,能认真的读读也是大有裨益的。
也是真的感叹Spirng作者们的功力之强,Spirng的扩展性有多少的强大。
安利时刻: