Spring启动流程

在这里插入图片描述

Spring启动流程的主要步骤及对应的代码如下:

  1. 启动入口,从main方法调用SpringApplication.run
    public class MyApplication {
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    }
    
  2. 初始化,创建SpringApplication实例,并设置初始化器和监听器。
    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return new SpringApplication(primarySource).run(args);
    }
    
    public SpringApplication(Object... sources) {
        initialize(sources);
    }
    
    private void initialize(Object[] sources) {
        this.sources = new LinkedHashSet<>(Arrays.asList(sources));
        this.initializers = getSpringFactoriesInstances(ApplicationContextInitializer.class);
        this.listeners = getSpringFactoriesInstances(ApplicationListener.class);
    }
    
  3. 配置环境,准备Spring环境,如读取配置文件、系统属性等。
    public ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
        // 创建并配置环境
        ConfigurableEnvironment environment = getOrCreateEnvironment();
        configureEnvironment(environment, applicationArguments.getSourceArgs());
        listeners.environmentPrepared(environment);
        return environment;
    }
    
  4. 创建上下文,根据应用类型创建合适的应用上下文。
    protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                contextClass = Class.forName(this.webApplicationType.getApplicationContextClassName());
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Unable to create a default ApplicationContext, "
                                + "please specify an ApplicationContextClass",
                        ex);
            }
        }
        return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
    }
    
  5. 刷新上下文,初始化所有单例Bean,启动Spring生命周期。
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            prepareBeanFactory(beanFactory);
            postProcessBeanFactory(beanFactory);
            invokeBeanFactoryPostProcessors(beanFactory);
            registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        }
    }
    
  6. 通知监听器启动完成,执行ApplicationRunnerCommandLineRunner
    private void callRunners(ApplicationContext context, ApplicationArguments args) {
        List<Object> runners = new ArrayList<>();
        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
        AnnotationAwareOrderComparator.sort(runners);
        for (Object runner : new LinkedHashSet<>(runners)) {
            if (runner instanceof ApplicationRunner) {
                callRunner((ApplicationRunner) runner, args);
            }
            if (runner instanceof CommandLineRunner) {
                callRunner((CommandLineRunner) runner, args);
            }
        }
    }
    

其中核心方法为refresh()刷新上下文方法。

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备刷新上下文
        prepareRefresh();

        // 2. 获取BeanFactory并进行初始化
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 3. 为BeanFactory配置上下文相关信息
        prepareBeanFactory(beanFactory);

        try {
            // 4. 子类覆盖方法,做进一步的BeanFactory初始化
            postProcessBeanFactory(beanFactory);

            // 5. 调用BeanFactoryPostProcessors
            invokeBeanFactoryPostProcessors(beanFactory);

            // 6. 注册BeanPostProcessors
            registerBeanPostProcessors(beanFactory);

            // 7. 初始化消息源(用于国际化)
            initMessageSource();

            // 8. 初始化事件广播器
            initApplicationEventMulticaster();

            // 9. 子类覆盖方法,在上下文刷新的时候进行进一步的处理
            onRefresh();

            // 10. 注册监听器以便监听事件
            registerListeners();

            // 11. 初始化所有单例Bean
            finishBeanFactoryInitialization(beanFactory);

            // 12. 完成刷新过程,通知生命周期处理器
            finishRefresh();
        }
        catch (BeansException ex) {
            // 如果在刷新过程中出现异常,则销毁已创建的单例Beans以避免资源泄漏
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        }
        finally {
            // 重置标志位
            resetCommonCaches();
        }
    }
}
  1. prepareRefresh准备刷新容器,此方法做一些刷新容器的准备工作:
    • 设置开启时间和对应标志位。
    • 获取环境对象。
    • 设置监听器和一些时间的集合对象。
  2. obtainFreshBeanFactory创建容器对象:DefaultListableBeanFactory;加载xml配置文件属性值到工厂中,最重要的是BeanDefinition
  3. prepareBeanFactory完成Bean工厂的某些初始化操作:
    • 设置BeanDefinition的类加载器。
    • 设置Spring容器默认的类型转换器。
    • 设置Spring解析EL表达式的解析器。
    • 添加一个Bean的后置处理器ApplicationContextAwareProcessor
    • 将Bean工厂的一些类,比如ApplicationContext直接注册到单例池中。
    • 去除一些在byType或者byName的时候需要过滤掉的一些Bean(Spring在依赖注入的时候会先在这些默认注册的Bean中进行byType找,如果找到了,就加入到列表中,简单来说就是比如你在Bean中依赖注入了ApplicationContext,那么Spring会把默认注册的这些Bean中找到然后进行注册)。
    • 将系统的环境信息、Spring容器的启动环境信息、操作系统的环境信息直接注册成一个单例的Bean。
  4. postProcessBeanFactory这里是一个空壳方法,Spring目前还没有对他进行实现;这个方法是留给子类进行实现的,后续可以添加一些用户自定义的或者默认的一些特殊的后置处理器工程到beanFactory中去。
  5. invokeBeanFactoryPostProcessors 调用后置处理器;将系统中所有符合条件的普通类都扫描成了一个BeanDefinition并且放入到了beanDefinitionMap中,包括业务的Bean,Bean的后置处理器、Bean工厂的后置处理器等。
    • 将标记为容器单例类扫描成BeanDefinition放入BeanDefinitionMap
    • 处理@Import注解。
    • 如果我们的配置类是@Configuration的,那么会生成这个配置类的CGLIB代理类,如果没有加@Configuration,则就是一个普通Bean。
  6. registerBeanPostProcessorsbeanDefinitionMap中取出Bean的后置处理器然后放入到后置处理器的缓存列表中。
  7. initMessageSource初始化国际化资源信息。
  8. initApplicationEventMulticaster事件注册器初始化。
  9. onRefresh空壳方法,留给子类实现。
  10. registerListeners将容器中和BeanDefinitionMap中的监听器添加到事件监听器中。
  11. finishBeanFactoryInitialization创建单例池,将容器中非懒加载的Bean,单例Bean创建对象放入单例池中,包括容器的依赖注入。
  12. finishRefresh容器启动过后,发布事件。
Spring启动过程可以分为以下几个步骤[^1]: 1. 创建Spring容器:通过创建一个ApplicationContext对象来启动Spring容器。可以使用不同的ApplicationContext实现类,如AnnotationConfigApplicationContext、ClassPathXmlApplicationContext等。 2. 解析配置类:如果使用AnnotationConfigApplicationContext启动容器,会解析配置类,将配置类中的Bean定义注册到容器中。 3. 准备启动:在容器准备启动之前,会执行一些准备工作,如初始化消息源、初始化事件广播器等。 4. 注册Bean后置处理器:在容器启动之前,会注册一些Bean后置处理器,用于在Bean实例化和初始化过程中进行一些额外的处理。 5. 初始化BeanFactory:在容器启动之前,会对BeanFactory进行一些初始化操作,如设置类加载器、设置Bean的后置处理器等。 6. 完成容器初始化:在容器启动之前,会完成BeanFactory的初始化工作,包括实例化和初始化所有的单例Bean。 7. 容器启动完成通知:在容器启动完成后,可以通过创建一个实现SmartLifecycle接口的类来监听容器启动完成的通知。 以下是一个示例代码,演示了Spring启动过程中的一些关键步骤: ```java import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.SmartLifecycle; import org.springframework.stereotype.Component; @Component public class Beanfinish implements SmartLifecycle { @Override public void start() { System.out.println("容器启动完成通知..."); } @Override public void stop() { } @Override public boolean isRunning() { return false; } @Override public boolean isAutoStartup() { return true; } } public class Main { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); context.start(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_whitepure

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值