Spring源码六——onRefresh()方法大家好,我是程序员田同学。今天就带大家解读一下Spirng第六篇源码的onRefresh()方法。这是refresh()的方法之一。看似是个空方法,其实对提高Spring的扩展性非常非常重要。老规矩,先贴出Spring核心方法refresh()方法的源码,方便读者顺利入戏。@Overridepublicvoidrefresh()throwsBeansException,IllegalStateException{synchronized(this.startupShutdownMonitor){//准备此上下文以进行刷新。//1。刷新前准备prepareRefresh();//告诉子类刷新内部bean工厂。//2、会初始化BeanFactory,加载Bean,注册BeanConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();//准备在此上下文中使用的bean工厂。//3、设置BeanFactory的类加载器,添加几个BeanPostProcessor,手动注册几个特殊的beanprepareBeanFactory(beanFactory);try{//4,模板方法//允许在上下文子类中对bean工厂进行后处理。postProcessBeanFactory(beanFactory);//调用在上下文中注册为beans的工厂处理器。//执行BeanFactory后处理器invokeBeanFactoryPostProcessors(豆工厂);//5.注册拦截bean创建的bean处理器。//注册bean后处理器registerBeanPostProcessors(beanFactory);//为这个上下文初始化消息源。//国际化initMessageSource();//为此context.initApplicationEventMulticaster()初始化事件多播器;//初始化特定上下文子类中的其他特殊bean。//6。模板方法--springboot实现了这个方法onRefresh();//检查侦听器bean并注册它们。//7。注册监听器registerListeners();//实例化所有剩余的(非惰性初始化)单例。//8。完成bean工厂的初始化**方法*************************************************finishBeanFactoryInitialization(beanFactory);//9、最后一步:发布相应的事件。完成刷新();}catch(BeansExceptionex){if(logger.isWarnEnabled()){logger.warn("上下文初始化期间遇到异常-"+"取消刷新尝试:"+ex);}//销毁已经创建的单例以避免悬空资源。destroyBeans();//重置“活动”标志。取消刷新(前);//将异常传播给调用者。扔前;}finally{//重置Spring核心中的通用内省缓存,因为我们//可能不再需要单例bean的元数据...resetCommonCaches();onRefresh()是一个模板方法,具体的子类可以在这里初始化一些特殊的bean(在初始化单例bean之前)。这是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()方法有什么作用?我们调试一下看看。ReactiveWebServerApplicationContext类的onRresh()方法还没有实现。名称和含义应该与webServer管理有关。限于篇幅,先留个坑吧。ServletWebServerApplicationContext类的onRefresh()方法已经执行完毕,我们进去一探究竟。privatevoidcreateWebServer(){WebServerwebServer=this.webServer;ServletContextservletContext=getServletContext();//第一次进入webServer时servletContext为null,会进入if分支具体看getWebServerFactory()方法,//还是ServletWebServerApplicationContext类的方法//创建了TomcatServletWebServerFactory类ServletWebServerFactoryfactory=getWebServerFactory();//创建Tomcatthis.webServer=factory.getWebServer(getSelfInitializer());}elseif(servletContext!=null){try{getSelfInitializer().onStartup(servletContext);}catch(ServletExceptionex){thrownewApplicationContextException("无法初始化servlet上下文",ex);}}initPropertySources();核心应该是factory.getWebServer(getSelfInitializer())。这个方法是创建一个容器。有哪些容器?我们来看看他的实现类,有Jetty、Mock、Tomcat*,Tomcat就不用说了,Jetty听说很容易和Tomcat绑在一起。那么什么是模拟?抱着求知的态度在百度上搜了一下,没看懂。交上来!我们仍然专注于Tomcat。进去看看TomcatServletWebServerFactory的实现类,new一个Tomcat对象,做一些Tomcat的设置,什么协议,端口...等等。@OverridepublicWebServergetWebServer(ServletContextInitializer...initializers){if(this.disableMBeanRegistry){Registry.disableRegistry();}//创建TomcatTomcattomcat=newTomcat();文件baseDir=(this.baseDirectory!=null)?this.baseDirectory:createTempDir("tomcat");tomcat.setBaseDir(baseDir.getAbsolutePath());//同步非阻塞io协议Connectorconnector=newConnector(this.protocol);connector.setThrowOnFailure(真);tomcat.getService().addConnector(连接器);自定义连接器(连接器);tomcat.setConnector(连接器);tomcat.getHost().setAutoDeploy(false);配置引擎(tomcat.getEngine());for(ConnectoradditionalConnector:this.additionalTomcatConnectors){tomcat.getService().addConnector(additionalConnector);}prepareContext(tomcat.getHost(),initializers);//这里会创建一个TomcatWebServer实例,并返回returngetTomcatWebServer(tomcat);}好了,这里是spirng模板,onRefresh()方法在Springboot中是如何工作的呢?为了说清楚,顺便简单介绍一下Springboot是如何嵌入Tomcat的。好像有点跑题了。说说onRefresh()方法,结果在springboot里绕了一大圈。不过也有助于读者更好地理解Spirng与Springboot的关系,认真阅读。也真是感叹Spirng的作者们的实力,Spirng的可扩展性是多么的强大。
