本文共 14289 字,大约阅读时间需要 47 分钟。
在上一篇文章中我们详细分析了spring boot是如何准备上下文环境的,今天我们来看一下run函数剩余的内容。还是先把run函数贴出来:
/** * Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @return a running {@link ApplicationContext} */ public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; CollectionexceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }
我们接着往下看,来看一下this.refreshContext(context);函数,这个函数用于刷新上下文,跟踪到源码看一下:
private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } }
在refreshContext函数中,第一行调用了refresh(context);跳转了一下,下面的代码是注册了一个应用关闭的函数钩子。
先来看refresh(context);函数:/** * Refresh the underlying {@link ApplicationContext}. * @param applicationContext the application context to refresh */ protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); }
通过代码跟踪分析发现,其实是调用了AbstractApplicationContext中的refresh方法。
在ServletWebServerApplicationContext和ReactiveWebServerApplicationContext的refresh函数中都是调用了super.refresh();public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory); try { this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var9) { if(this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization \ - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }
在这段代码中我们可以看到,其是使用了上下文中的startupShutdownMonitor属性创建一个同步代码库来执行的刷新动作。首先是实验this.prepareRefresh();准备刷新上下文:
protected void prepareRefresh() { this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if(this.logger.isInfoEnabled()) { this.logger.info("Refreshing " + this); } this.initPropertySources(); this.getEnvironment().validateRequiredProperties(); this.earlyApplicationEvents = new LinkedHashSet(); }
接着获取了bean工厂以后,设置了一些bean工厂的环境:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.setBeanClassLoader(this.getClassLoader()); beanFactory.setBeanExpressionResolver( new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar( new ResourceEditorRegistrar(this, this.getEnvironment())); beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); if(beanFactory.containsBean("loadTimeWeaver")) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader( new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } if(!beanFactory.containsLocalBean("environment")) { beanFactory.registerSingleton("environment", this.getEnvironment()); } if(!beanFactory.containsLocalBean("systemProperties")) { beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties()); } if(!beanFactory.containsLocalBean("systemEnvironment")) { beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment()); } }
接下来是发送了一个bean工厂的处理信号,其中ServletWebServerApplicationContext中的实现是在bean工厂里添加了一个WebApplicationContextServletContextAwareProcessor处理器:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.addBeanPostProcessor( new WebApplicationContextServletContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); }
紧接着就是调用了这处理器,并且注册到bean工厂。然后就是分别调用了initMessageSource()和initApplicationEventMulticaster()用于初始化监听器和监听管理器:
protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = this.getBeanFactory(); if(beanFactory.containsLocalBean("messageSource")) { this.messageSource = (MessageSource)beanFactory .getBean("messageSource", MessageSource.class); if(this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource dms = (HierarchicalMessageSource)this.messageSource; if(dms.getParentMessageSource() == null) { dms.setParentMessageSource(this.getInternalParentMessageSource()); } } if(this.logger.isDebugEnabled()) { this.logger.debug("Using MessageSource [" + this.messageSource + "]"); } } else { DelegatingMessageSource dms1 = new DelegatingMessageSource(); dms1.setParentMessageSource(this.getInternalParentMessageSource()); this.messageSource = dms1; beanFactory.registerSingleton("messageSource", this.messageSource); if(this.logger.isDebugEnabled()) { this.logger.debug("Unable to locate MessageSource with name \'messageSource\': using default [" + this.messageSource + "]"); } } } protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = this.getBeanFactory(); if(beanFactory.containsLocalBean("applicationEventMulticaster")) { this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory .getBean("applicationEventMulticaster", ApplicationEventMulticaster.class); if(this.logger.isDebugEnabled()) { this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster); if(this.logger.isDebugEnabled()) { this.logger.debug("Unable to locate ApplicationEventMulticaster with name \'applicationEventMulticaster\': using default [" + this.applicationEventMulticaster + "]"); } } }
在initMessageSource函数中会首先判断beanFactory工厂中是否已经存在messageSource,如果不存在就会为当前的messageSource创建一个新的DelegatingMessageSource。
initApplicationEventMulticaster的初始化方式跟initMessageSource差不多,这里不再多述。 继续看run函数,接下来调用onRefresh()函数,这个函数只是发送一个刷新的事件,源码中并没有具体的实现。 接着放下看,this.registerListeners();把spring容器内的listener和beanfactory的listener都添加到广播器中:protected void registerListeners() { Iterator listenerBeanNames = this.getApplicationListeners().iterator(); while(listenerBeanNames.hasNext()) { ApplicationListener earlyEventsToProcess = (ApplicationListener)listenerBeanNames.next(); this.getApplicationEventMulticaster().addApplicationListener(earlyEventsToProcess); } String[] var6 = this.getBeanNamesForType(ApplicationListener.class, true, false); String[] var7 = var6; int var3 = var6.length; for(int earlyEvent = 0; earlyEvent < var3; ++earlyEvent) { String listenerBeanName = var7[earlyEvent]; this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } Set var8 = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if(var8 != null) { Iterator var9 = var8.iterator(); while(var9.hasNext()) { ApplicationEvent var10 = (ApplicationEvent)var9.next(); this.getApplicationEventMulticaster().multicastEvent(var10); } } }
通过this.finishBeanFactoryInitialization(beanFactory);实例化BeanFactory 中已经被注册但是没被实例化的所有实例。初始化的过程中各种BeanPostProcessor就开始生效了:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { if(beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) { beanFactory.setConversionService((ConversionService)beanFactory .getBean("conversionService", ConversionService.class)); } if(!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver((strVal) -> { return this.getEnvironment().resolvePlaceholders(strVal); }); } String[] weaverAwareNames = beanFactory .getBeanNamesForType(LoadTimeWeaverAware.class, false, false); String[] var3 = weaverAwareNames; int var4 = weaverAwareNames.length; for(int var5 = 0; var5 < var4; ++var5) { String weaverAwareName = var3[var5]; this.getBean(weaverAwareName); } beanFactory.setTempClassLoader((ClassLoader)null); beanFactory.freezeConfiguration(); beanFactory.preInstantiateSingletons(); }
接下来调用finishRefresh()函数用于完成刷新后的一些扫尾工作,包括产生的缓存、初始化生命周期处理器LifecycleProcessor,并调用其onRefresh()方法、发布事件、调用LiveBeansView的registerApplicationContext注册context。
protected void finishRefresh() { this.clearResourceCaches(); this.initLifecycleProcessor(); this.getLifecycleProcessor().onRefresh(); this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this))); LiveBeansView.registerApplicationContext(this); }
接着看run函数,在刷新完context后,调用了一个afterRefresh函数,这个函数前面已经说过了,是为了给ApplicationContext的子类留下的一个扩展点。
然后调用了listeners.started(context);,把监听器设置成了已经启动的状态。 最后调用了callRunners函数,获取所有的ApplicationRunner和CommandLineRunner然后调用他们的run方法:private void callRunners(ApplicationContext context, ApplicationArguments args) { List
总结:spring boot 2.0在启动的时候,首先会调用SpringApplication的构造函数进行初始化,调用实例函数run,在run函数中,首先获取监听器,并设置成启动状态,后面准备环境prepareEnvironment,准备prepareContext上下文,刷新上下文refreshContext,最后调用callRunners来依次调用注册的Runner。
转载地址:http://dtqtx.baihongyu.com/