博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring boot 2.0 源码分析(五)
阅读量:5941 次
发布时间:2019-06-19

本文共 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;        Collection
exceptionReporters = 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 runners = new ArrayList<>();        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());        AnnotationAwareOrderComparator.sort(runners);        for (Object runner : new LinkedHashSet<>(runners)) {            if (runner instanceof ApplicationRunner) {                callRunner((ApplicationRunner) runner, args);            }            if (runner instanceof CommandLineRunner) {                callRunner((CommandLineRunner) runner, args);            }        }    }

总结:spring boot 2.0在启动的时候,首先会调用SpringApplication的构造函数进行初始化,调用实例函数run,在run函数中,首先获取监听器,并设置成启动状态,后面准备环境prepareEnvironment,准备prepareContext上下文,刷新上下文refreshContext,最后调用callRunners来依次调用注册的Runner。

转载地址:http://dtqtx.baihongyu.com/

你可能感兴趣的文章
Contact Bubble View
查看>>
MKTickerView
查看>>
objective-c 面试题
查看>>
定制适合自己的精简桌面环境
查看>>
【Thread】简单说说java.lang.Thread.State
查看>>
开源 java CMS - FreeCMS2.3 会员组管理
查看>>
开源 java CMS - FreeCMS2.6 静态化管理
查看>>
开源 java CMS - FreeCMS2.8 数据对象 applyopen
查看>>
UI控件
查看>>
自己整合优化的一个Android框架
查看>>
Android内核剖析 目录
查看>>
jsf如何通过按钮切换在同一个页面上的非公共部分显示不同的内容
查看>>
/etc/fstab 文件解释
查看>>
如何用函数表示数(四)数的彻底消失
查看>>
windows 7下同时安装visual studio 2012和2010
查看>>
android--------Socket的简单了解
查看>>
安卓错误Emulator: error: x86 emulation currently......
查看>>
Asynchronous CDI Events
查看>>
mynginx.conf
查看>>
Oracle——20数据库恢复与备份
查看>>