SpringBoot的启动过程

SpringBoot过程描述图
在这里插入图片描述

查看它的源码实现

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        SpringApplication.run(ZhStateApplication.class, args);
}

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class[]{primarySource}, args);
}

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
}

由上面源码可以看到,启动run方法其实分两部分
一是创建一个SpringApplication对象,二是调用run方法

new SpringApplication(primarySources),其中primarySources就是启动类的Class对象

public SpringApplication(Class<?>... primarySources) {
        this((ResourceLoader)null, primarySources);
}

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    	// 设置初始值
        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");
        // primarySources: 代表主要资源的Set<Class>集合,将传入的启动类资源加入到primarySources
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        // webApplicationType:应用程序类型,默认为Servlet 
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.bootstrapRegistryInitializers = this.getBootstrapRegistryInitializersFromSpringFactories();
        // 1. 设置初始化,根据ApplicationContextInitializer去spring.factories文件中找到对应的数据,通过反射创建对象集合,然后赋值给initializers集合
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        // 2. 设置监听器,根据ApplicationListener去spring.factories文件中找到对应的数据,通过反射创建对象集合,然后赋值给listeners集合,他的逻辑根上面方法一样
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    	// 找到包含main函数的启动类的Class对象赋值给mainApplicationClass
        this.mainApplicationClass = this.deduceMainApplicationClass();
}
  1. 设置初始化
// SpringApplication类
// 1. 设置初始化
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
       // 1.1 获取SpringFactories中指定的集合对象
        return this.getSpringFactoriesInstances(type, new Class[0]);
    }

1.1 获取SpringFactories中指定的集合对象

// SpringApplication类
// 1.1 获取SpringFactories中指定的集合对象
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    	// 获取类加载器
        ClassLoader classLoader = this.getClassLoader();
       // 1.1.1 获取加载工厂的名称
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        // 根据names集合来通过反射创建对象集合
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

1.1.1 获取加载工厂的名称

// SpringFactoriesLoader 类
// 1.1.1  获取加载工厂的名称
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        ClassLoader classLoaderToUse = classLoader;
        if (classLoader == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }
        String factoryTypeName = factoryType.getName();
    	// loadSpringFactories(classLoaderToUse): 加载META-INF/spring.factories文件里面的数据
    	// getOrDefault(factoryTypeName, Collections.emptyList()): 根据指定的工厂类型名称过滤
        return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
    }
// 根据指定类加载器,来加载META-INF/spring.factories文件里面的数据
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
        Map<String, List<String>> result = (Map)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            HashMap result = new HashMap();

            try {
                Enumeration urls = classLoader.getResources("META-INF/spring.factories");

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        String[] var10 = factoryImplementationNames;
                        int var11 = factoryImplementationNames.length;

                        for(int var12 = 0; var12 < var11; ++var12) {
                            String factoryImplementationName = var10[var12];
                            ((List)result.computeIfAbsent(factoryTypeName, (key) -> {
                                return new ArrayList();
                            })).add(factoryImplementationName.trim());
                        }
                    }
                }

                result.replaceAll((factoryType, implementations) -> {
                    return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
                });
                cache.put(classLoader, result);
                return result;
            } catch (IOException var14) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
            }
        }
    }

第二部分run(args)

// SpringApplication类
// 2. 运行Spring应用程序,创建并刷新一个新的ApplicationContext
public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
    	// 异常报告信息
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty(); // 向当前系统设置了一个属性
    	// 1.1 获取SpringFactories中指定的集合对象SpringApplicationRunListener
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
    	// 遍历监听器集合执行
        listeners.starting();
        try {
            // 将入参的数组包装成一个DefaultApplicationArguments对象
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 准备环境对象
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            // 配置忽略的Bean信息
            this.configureIgnoreBeanInfo(environment);
            // 打印Banner图案,也可以自定义图案
            Banner printedBanner = this.printBanner(environment);
            // 创建应用程序上下文对象
            context = this.createApplicationContext();
            // 获取SpringFactories中指定的集合对象SpringBootExceptionReporter
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            // 准备上下文,也就是向上下文设置一些值
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            // 刷新上下文,也就是调用了Spring的 refresh方法
            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, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值