SpringBoot | 源码解析(一): SpringApplication.run

前言

由于最近个人工作不太繁忙,之前想看SpringBoot 源码, 今天终于能研究研究了。个人简单过了一边SpringApplication.run() 方法的流程 这里记录一下。

这里将run方法中一些比较复杂的方法 在代码中加了注释

有错误希望指正

SpringApplication.run() 方法 看注释

public ConfigurableApplicationContext run(String... args) {
		//创建时间记录类&启动时间记录
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		
		//变量
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		
		//设置系统属性
		configureHeadlessProperty();
		
		//创建所有 Spring 运行监听器并发布应用启动事件 
		//遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//告诉这些SpringApplicationRunListener SpringBoot开始执行了
		listeners.starting();
		try {
			//初始化对象
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			
			//加载服务&系统资源
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			
			//打印SpringBoot 启动日志   就那个图形化日志
			//Banner的日志
			Banner printedBanner = printBanner(environment);

			//通过SpringBoot 初始化获得的 容器类型 创建响应的ConfigurableApplicationContext 
			context = createApplicationContext();

			//再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,		   	然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context);
			//获取 对创建的context 进行封装 将environment 赋值到Context中
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);

			//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;
}

configureHeadlessProperty()

//在System系统中设置 属性
private void configureHeadlessProperty() {
        System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));
    }

getRunListeners()

//创建所有 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() & configureIgnoreBeanInfo()

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 对象 会获取到配置等信息

printBanner()

//打印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);
        }
    }

在这里插入图片描述
服务启动 打印图形化日志 那个方法

createApplicationContext();

//创建 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);
    }

getSpringFactoriesInstances()

// 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;
    }

prepareContext()

//对进行 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()

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();
    }

如果对你有帮助,加个关注把~
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一介草民丶

谢谢老板的一分钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值