由于最近个人工作不太繁忙,之前想看SpringBoot 源码, 今天终于能研究研究了。个人简单过了一边SpringApplication.run() 方法的流程 这里记录一下。
这里将run方法中一些比较复杂的方法 在代码中加了注释
有错误希望指正!
public ConfigurableApplicationContext run(String... args) { //创建时间记录类&启动时间记录 StopWatch stopWatch = new StopWatch(); stopWatch.start(); //变量 ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); //设置系统属性 configureHeadlessProperty(); //创建所有 Spring 运行监听器并发布应用启动事件 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { //初始化对象 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //加载服务&系统资源 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); //打印SpringBoot 启动日志 就那个图形化日志 //Banner的日志 Banner printedBanner = printBanner(environment); //创建ConfigurableApplicationContext context = createApplicationContext(); // springboot 自动装配 方法 获取 META-INF/spring.factories 文件下的所有 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner);//获取 context 封装 //spring 核心方法 内部调用 ((AbstractApplicationContext) applicationContext).refresh() 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; }
//在System系统中设置 属性 private void configureHeadlessProperty() { System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless))); }
//创建所有 Spring 运行监听器并发布应用启动事件 private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class[]{SpringApplication.class, String[].class}; return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)); }
prepareEnvironment()
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { ConfigurableEnvironment environment = this.getOrCreateEnvironment(); this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs()); ConfigurationPropertySources.attach((Environment)environment); listeners.environmentPrepared((ConfigurableEnvironment)environment); this.bindToSpringApplication((ConfigurableEnvironment)environment); if (!this.isCustomEnvironment) { environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass()); } ConfigurationPropertySources.attach((Environment)environment); return (ConfigurableEnvironment)environment; }
configureIgnoreBeanInfo()
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) { if (System.getProperty("spring.beaninfo.ignore") == null) { Boolean ignore = (Boolean)environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE); System.setProperty("spring.beaninfo.ignore", ignore.toString()); } }
//加载服务&系统资源
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
这一步 会获取到上图的 environment 对象 会获取到配置等信息
//打印SpringBoot 启动日志 就那个图形化日志 private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Mode.OFF) { return null; } else { ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader(this.getClassLoader()); SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter((ResourceLoader)resourceLoader, this.banner); return this.bannerMode == Mode.LOG ? bannerPrinter.print(environment, this.mainApplicationClass, logger) : bannerPrinter.print(environment, this.mainApplicationClass, System.out); } }
服务启动 打印图形化日志 那个方法
//创建 ConfigurableApplicationContext 对象 protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch(this.webApplicationType) { case SERVLET: contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext"); break; case REACTIVE: contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"); break; default: contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext"); } } catch (ClassNotFoundException var3) { throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3); } } return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass); }
// springboot 自动装配 方法 获取 META-INF/spring.factories 文件下的所有 private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = this.getClassLoader(); //loadFactoryNames()这个方法中 调用 loadSpringFactories(@Nullable ClassLoader classLoader) 方法 这个方法是加载 META-INF/spring.factories 文件中的内容 Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
//对进行 context 封装 将BeanFactory 赋值 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); this.postProcessApplicationContext(context); this.applyInitializers(context); listeners.contextPrepared(context); if (this.logStartupInfo) { this.logStartupInfo(context.getParent() == null); this.logStartupProfileInfo(context); } ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments); if (printedBanner != null) { beanFactory.registerSingleton("springBootBanner", printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } Set<Object> sources = this.getAllSources(); Assert.notEmpty(sources, "Sources must not be empty"); this.load(context, sources.toArray(new Object[0])); listeners.contextLoaded(context); }
refreshContext( ) 方法 调用是 refresh( )方法 Spring 的入口
//spring 核心方法 内部调用 ((AbstractApplicationContext) applicationContext).refresh()
这里就需要对Spring的源码需要了解了
//Spring 核心方法 内部调用 ((AbstractApplicationContext) applicationContext).refresh() protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext)applicationContext).refresh(); }