本文共 8897 字,大约阅读时间需要 29 分钟。
通过之前的学习我们大致上已经知道了SpringBoot启动的流程。到目前剩下的就是如何将BeanDefineMap中的类转化为真实的bean,然后注册到beanFactory的beanMap中了。那么onRefresh方法是否就是做这件事情的?
protected void onRefresh() { super.onRefresh(); try { this.createWebServer(); } catch (Throwable var2) { throw new ApplicationContextException("Unable to start web server", var2); }}
我们看到在GenericWebApplicationContext中调用了
UiApplicationContextUtils.initThemeSource(this);方法。继续跟踪,我们进入initThemeSource这个方法。
public static ThemeSource initThemeSource(ApplicationContext context) { if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {//themeSource是否存在,不存在的时候创建,这里的getBean方法是关键 ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class); // Make ThemeSource aware of parent ThemeSource. if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) { HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource; if (hts.getParentThemeSource() == null) { // Only set parent context as parent ThemeSource if no parent ThemeSource // registered already. hts.setParentThemeSource((ThemeSource) context.getParent()); } } if (logger.isDebugEnabled()) { logger.debug("Using ThemeSource [" + themeSource + "]"); } return themeSource; } else {//创建themeSource对象并返回。 // Use default ThemeSource to be able to accept getTheme calls, either // delegating to parent context's default or to local ResourceBundleThemeSource. HierarchicalThemeSource themeSource = null; if (context.getParent() instanceof ThemeSource) { themeSource = new DelegatingThemeSource(); themeSource.setParentThemeSource((ThemeSource) context.getParent()); } else { themeSource = new ResourceBundleThemeSource(); } if (logger.isDebugEnabled()) { logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME + "': using default [" + themeSource + "]"); } return themeSource; }}//创建web服务 private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = this.getServletContext(); if (webServer == null && servletContext == null) { ServletWebServerFactory factory = this.getWebServerFactory(); this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()}); } else if (servletContext != null) { try { this.getSelfInitializer().onStartup(servletContext); } catch (ServletException var4) { throw new ApplicationContextException("Cannot initialize servlet context", var4); } } this.initPropertySources(); }
这块是获取tomcat的,通过ServletWebServerFactory拿取servlet服务器
protected ServletWebServerFactory getWebServerFactory() { String[] beanNames = this.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class); if (beanNames.length == 0) { throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean."); } else if (beanNames.length > 1) { throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } else { return (ServletWebServerFactory)this.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class); }}
代码运行到这里的时候,tomcat已经加载好了。
protected void initPropertySources() { ConfigurableEnvironment env = this.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null); }}
又进行了一次配置修改
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);}
创建完servlet服务器之后,就开始注册registerListener。这块就是上篇文档我们说到的ApplicationListenner接口。
执行完上述操作之后,我们看看finishBeanFactoryInitialization是做那些工作的。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons();}
通过debug发现,这个方法对bean进行实例化。
通过这个方法之后,singletonObjects被逐渐转化为bean实体。
在finishRefresh方法中
protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning). clearResourceCaches(); // 初始化一个处理器initLifecycleProcessor(); // 拿到处理器,并初始化lifecycle接口的类 getLifecycleProcessor().onRefresh(); // 发布容器已经刷新的消息 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this);}
初始化有lifecycle接口的类
protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) { this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class); if (logger.isTraceEnabled()) { logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]"); } } else { DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor(); defaultProcessor.setBeanFactory(beanFactory); this.lifecycleProcessor = defaultProcessor; beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor); if (logger.isTraceEnabled()) { logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " + "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]"); } }}
// 这里开始调用lifecycle接口bean的方法private void startBeans(boolean autoStartupOnly) {//获取实现了lifecycle接口的bean Map, Lifecycle> lifecycleBeans = getLifecycleBeans(); Map, LifecycleGroup> phases = new HashMap<>(); lifecycleBeans.forEach((beanName, bean) -> { if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) { int phase = getPhase(bean); LifecycleGroup group = phases.get(phase); if (group == null) { group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly); phases.put(phase, group); } group.add(beanName, bean); } }); if (!phases.isEmpty()) { Listkeys =new ArrayList<>(phases.keySet()); Collections.sort(keys); for (Integer key : keys) { phases.get(key).start(); } }}
但是分析到这里就比较奇特了,这里只是启动启动了tomcat,那么tomcat是在哪里创建的?
我跟踪代码.
我们发现在OnRefresh方法中就创建了。我们看到OnRefresh方法有4个实现。
我们依次查看源代码,看看实现有什么差别。发现ServletWebServerApplicationContent和ReactiveWebServerApplicationContent都有Servlet容器服务的创建。
在这里突然想到,如果我们不做服务端也就是不想启动servlet容器,那么是不是就不用用剩余的两个content类?如果是这样的话,那么肯定在创建这里的content时候就决定了。我们知道当时创建content容器的时候得方法是createApplicationContent方法。
那么是不是我们设置了webApplicationType就可以了?通过研究发现确实是这样的。其实我一直觉得控制是否启动servlet容器的控制在于OnRefresh中,现在发现spring调用前就决定了一切。
SpringApplicationBuilder builder = new SpringApplicationBuilder(MergeeServic.class);ApplicationContext applicationContext = builder.web(WebApplicationType.NONE).headless(false).run(args);
通过上述分析,springboot的过程已经解析的基本明确了。
转载地址:http://uhkmi.baihongyu.com/