SpringApplication的启动过程

参考视频:

https://www.ixigua.com/7090148232243708446?wid_try=1

public class SpringApplication {
    ...
    ...
    单参数构造方法
    public SpringApplication(Class... primarySources) {
        调用双参构造方法
        this((ResourceLoader)null, primarySources);
    }
    双参数构造方法
    public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
        这个构造函数相当于初始化各种属性参数等操作.......
        在1.0之前这个构造函数是作为init方法存在.........
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = Collections.emptySet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
        this.applicationStartup = ApplicationStartup.DEFAULT;
        this.resourceLoader = resourceLoader;
        断言你传过来的字节码文件不能为空,如果为空就给你打印后面这句话
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.bootstrapRegistryInitializers = this.getBootstrapRegistryInitializersFromSpringFactories();
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }
    ...
    ...
    run方法
    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        生成一个新的数组,数组里存的是Class类型,这些class从哪来,从字节码文件中来。
        return run(new Class[]{primarySource}, args);
    }
    ...
    ...
    另一个run方法
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        这里调用了SpringApplication的第一个构造函数
        return (new SpringApplication(primarySources)).run(args);
    }
    ...
    ...
    另另一个run方法
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        springboot当中用到的最早的一个配置文件类型,它优先加载于application.properties
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            加载环境变量,运行起来控制台会输出类似的Starting Application using Java 1.8.0_131 on PC-202032 with PID 5060(D://.......)
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            控制台打印的花式文字
            Banner printedBanner = this.printBanner(environment);
            创建了spring的核心容器
            context = this.createApplicationContext();
            让你的核心容器跑起来
            context.setApplicationStartup(this.applicationStartup);
            预处理
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            刷新整理
            this.refreshContext(context);
            最后刷新
            this.afterRefresh(context, applicationArguments);
            
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }

            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }
    
    
}

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    // 调用了当前类下的另一个run方法
    return run(new Class[]{primarySource}, args);
}
 
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    // 在当前类下的另一个run方法中 调用了当前类的单参构造方法
    return (new SpringApplication(primarySources)).run(args);
}

public SpringApplication(Class... primarySources) {
    // 单参构造方法中,又去调用了双参构造方法
    this((ResourceLoader)null, primarySources);
}

// 在双参构造方法中有这么一个ApplicationContextFactory
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;

public class StopWatch {
        ...
        ...
        public void start(String taskName) throws IllegalStateException {
            if (this.currentTaskName != null) {
                throw new IllegalStateException("Can't start StopWatch: it's already running");
            } else {
                this.currentTaskName = taskName;
                this.startTimeNanos = System.nanoTime();
            }
        }

}

它这个run要这个类的字节码有什么用呢? 它这个类上面的注解@SpringBootApplication

SpringUtils中的setApplicationContext到底什么时候被执行了?今天我们研究一下。

参考链接:ApplicationContextAware接口的setApplicationContext方法调用过程_大家说的博客-CSDN博客_setapplicationcontext方法


@Component
public class SpringUtils implements ApplicationContextAware {
    ...
    ...
    ...
    private ApplicationContext applicationContext;
    private BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
    private DefaultListableBeanFactory autowireCapableBeanFactory;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (this.applicationContext == null) {
            this.applicationContext = applicationContext;
        }
    }
    ...
    ...
}

    

SpringApplication.java:

public class SpringApplication {
    ...
    ...
    /**
	 * Refresh the underlying {@link ApplicationContext}.
	 * @param applicationContext the application context to refresh
	 */
	protected void refresh(ConfigurableApplicationContext applicationContext) {
		applicationContext.refresh();
	}
    ...
    ...
}

点击refresh进入ConfigurableApplicationContext 接口

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
    ....
    ....

    void refresh() throws BeansException, IllegalStateException;

    ....
    ....
}

点击抽象方法refresh() ,进入实现类AbstractApplicationContext.java

 
在refresh()方法中 点击this.prepareBeanFactory(beanFactory);// 点击进入查看prepareBeanFactory()

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    ...
    ...
     public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
   1这里---->this.prepareBeanFactory(beanFactory);//---->beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));---->ApplicationContextAwareProcessor.java

            try {
                this.postProcessBeanFactory(beanFactory);
                StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                beanPostProcess.end();
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
      4这里---->this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var10) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
                }

                this.destroyBeans();
                this.cancelRefresh(var10);
                throw var10;
            } finally {
                this.resetCommonCaches();
                contextRefresh.end();
            }

        }
    }
    ...
    ...
    ...
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setBeanClassLoader(this.getClassLoader());
        if (!shouldIgnoreSpel) {
            beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        }

        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
2这里---->beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
3这里---->ApplicationContextAwareProcessor.java
        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.ignoreDependencyInterface(ApplicationStartupAware.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 (!NativeDetector.inNativeImage() && 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());
        }

        if (!beanFactory.containsLocalBean("applicationStartup")) {
            beanFactory.registerSingleton("applicationStartup", this.getApplicationStartup());
        }

    }

    ....
    ....
5这里---->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();
6这里---->beanFactory.preInstantiateSingletons();
    }
    ....
}

在AbstractApplicationContext .java的refresh()的prepareBeanFactory()中查看:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

 

我们看到一个new ApplicationContextAwareProcessor(this)类,这个类是一个BeanPostProcessor类型的类。OK,我们先在这里有一个印象,就是在BeanFactory里面加入了一个 ApplicationContextAwareProcessor。
这个过程就是ApplicationContextAwareProcessor的装配过程。

---------------------------------------------------------------------------

AbstractApplicationContext.java的refresh()方法中继续往下执行,执行到AbstractApplicationContext .java的实例化bean的方法
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
代码执行到这个方法。

  • protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)

在AbstractApplicationContext.java的finishBeanFactoryInitialization()方法中:

会执行beanFactory.preInstantiateSingletons();

最终会执行到:

  • AbstractAutowireCapableBeanFactory#doCreateBean方法

方法当中:

Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }

点进去

在这里插入图片描述

 这个方法就是调用 ApplicationContextAwareProcessor的地方,我们进去看看。

在这里插入图片描述

我们可以看到,确实在BeanPostProcessors容器中有一个ApplicationContextAwareProcessor类。那么我们进到ApplicationContextAwareProcessor这个类的postProcessBeforeInitialization方法中。

在这里插入图片描述

在这里插入图片描述 根据这个源码,我们知道了,确实调用到了setApplicationContext()方法。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值