《springboot源码》1.springboot源码分析之启动流程分析

xiaoxiao2022-06-11  20

自负:

          自恃过高是自负者最显著的特点,一件事之所以不好,都是因为是别人做而不是自己做的。认为自己是天才,很少去关心别人,与他人关系比较疏远, 觉得别人和他无法沟通。这种人时时事事都从自己的利益出发,从不顾及别人,当对别人没有需要的时候,对人没有丝毫的热情,似乎人人都应为他服务,因为他比所有人都强,但是实际上他只会落得个门厅冷落。

克服自负:

          既要看到自己的短处,也要看到自己的长处,既要看到过去,又要看到自己的现在和将来。辉煌的过去可能标志春你曾经是个英雄,但它并不代表春现在你还是一个英雄。

         接受别人的正确观点,明白什么叫求同存异,通过接受别人的批评,改变过去唯我独尊的形象。

 

springboot启动  SpringApplication.run(xxx.class, args); 

我们看一下SpringApplication的run方法. 这是springboot的核心.

/** 在SpringApplication中 * 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; FailureAnalyzers analyzers = null; configureHeadlessProperty(); //1.启动监听器 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); //2.配置环境 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); //3.创建applicationContext context = createApplicationContext(); analyzers = new FailureAnalyzers(context); //4.准备容器,加载bean prepareContext(context, environment, listeners, applicationArguments, printedBanner); //5.刷新上下文 refreshContext(context); // 6.刷新上下文结束后 afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }

着重看一下第四步,准备容器

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); postProcessApplicationContext(context); applyInitializers(context); listeners.contextPrepared(context); if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans context.getBeanFactory().registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); } // Load the sources Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[sources.size()])); listeners.contextLoaded(context); }

applyInitializers(context);  实例化了许多bean 

private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) { List<T> instances = new ArrayList<T>(names.size()); for (String name : names) { try { Class<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass); Constructor<?> constructor = instanceClass .getDeclaredConstructor(parameterTypes); T instance = (T) BeanUtils.instantiateClass(constructor, args); instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException( "Cannot instantiate " + type + " : " + name, ex); } } return instances; }

我们发现最终通过反射机制实例化了bean

看一下第6步,刷新容器

//在AbstractApplicationContext中 @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }

实例化bean的方法我就不说了,   看下onRefresh()方法,这个方法被子类实现.

EmbeddedWebApplicationContext 实现了onRefresh()方法

//在EmbeddedWebApplicationContext中 @Override protected void onRefresh() { super.onRefresh(); try { createEmbeddedServletContainer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start embedded container", ex); } } private void createEmbeddedServletContainer() { EmbeddedServletContainer localContainer = this.embeddedServletContainer; ServletContext localServletContext = getServletContext(); if (localContainer == null && localServletContext == null) { EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory(); this.embeddedServletContainer = containerFactory .getEmbeddedServletContainer(getSelfInitializer()); } else if (localServletContext != null) { try { getSelfInitializer().onStartup(localServletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); }

老衲没猜错的话,  这就是tomcat真身吧 ,TomcatEmbeddedServletContainer 实现了EmbeddedServletContainer

debug跑了一下,正如我所料!

总结:  通过反射机制实例化了bean, bean的管理用的工厂模式.  里面AbstractApplicationContext的refresh模版模式

转载请注明原文地址: https://www.6miu.com/read-4930228.html

最新回复(0)