中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

SpringBoot啟動(dòng)流程-創(chuàng)新互聯(lián)

使用的SpringBoot版本為2.3.12,配套Spring版本為5.2.15

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、網(wǎng)絡(luò)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、內(nèi)鄉(xiāng)網(wǎng)站維護(hù)、網(wǎng)站推廣。一 SpringBoot啟動(dòng)流程 1.程序入口
// 程序入口
// 運(yùn)行SpringApplication.run方法
// 主啟動(dòng)類方法
// args是啟動(dòng)參數(shù),我在環(huán)境配置處配置程序參數(shù)了--server.port=8079端口號(hào)信息,則args不為空
public static void main(String[] args) {
    // 加載完成后 執(zhí)行run方法
    SpringApplication.run(SpringbootQuartzApplication.class, args);
}

// 上面代碼實(shí)際上是調(diào)用spring-boot包里的SpringApplication.class里的方法
// 這里可以看出是先創(chuàng)建SpringApplication對(duì)象,再調(diào)用run方法完成容器的初始化操作
public static ConfigurableApplicationContext run(Class[] primarySources, String[] args) {
    return (new SpringApplication(primarySources)).run(args);
}
2.主體分為兩個(gè)步驟

a.構(gòu)造方法創(chuàng)建SpringApplication實(shí)例

b.執(zhí)行SpringApplication實(shí)例的run方法

3.圖示 二 new SpringAoolication()構(gòu)造函數(shù)

隨版本不同,代碼會(huì)有較大差異,具體根據(jù)自己所用項(xiàng)目來(lái)。下面截取構(gòu)造方法核心部分代碼。

// new SpringApplication()構(gòu)造函數(shù)
public static ConfigurableApplicationContext run(Class[] primarySources, String[] args) {
    return (new SpringApplication(primarySources)).run(args);
}
其中new SpringApplication(primarySources)構(gòu)造函數(shù)環(huán)節(jié)調(diào)用的也是SpringApplication.class里的方法

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

// 下面會(huì)逐一展開(kāi)run方法執(zhí)行時(shí),是如何使用構(gòu)造方法里定義的屬性的
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
    // 1.初始化啟動(dòng)時(shí)必要參數(shù)
    this.sources = new LinkedHashSet();
    this.bannerMode = Mode.CONSOLE;
    // 打印JVM的啟動(dòng)和運(yùn)行信息,啟動(dòng)類、java版本等
    this.logStartupInfo = true;
    // 通過(guò)命令行參數(shù)向application.properties中添加屬性配置
    this.addCommandLineProperties = true;
    // 加載默認(rèn)的類型轉(zhuǎn)換和格式化類
    this.addConversionService = true;
    // 開(kāi)啟java的headless模式,此模式允許java在沒(méi)有顯示器、鼠標(biāo)等設(shè)備的情況下啟動(dòng)服務(wù)
    this.headless = true;
    // 創(chuàng)建線程,該線程用來(lái)在java程序關(guān)閉后釋放資源
    this.registerShutdownHook = true;
    // 默認(rèn)為空,即使用springboot默認(rèn)配置文件。開(kāi)發(fā)時(shí)切dev/sit/prod等分支時(shí)會(huì)使用
    this.additionalProfiles = new HashSet();
    // 是否加載環(huán)境配置
    this.isCustomEnvironment = false;
    // 是否懶加載,可以通過(guò)在application.properties設(shè)置spring.main.lazy-initialization=true修改
    this.lazyInitialization = false;
    // 
    this.resourceLoader = resourceLoader;
    // 主配置為空則拋出異常
    Assert.notNull(primarySources, "PrimarySources must not be null");
    // 保存主配置類
    this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    // 2 確認(rèn)web應(yīng)用類型,本項(xiàng)目為Servlet
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 3.加載所有初始化器,獲取spring工廠文件中的實(shí)例。加載了當(dāng)前項(xiàng)目下全部的spring.factries文件,將文件中的k-v放入緩存中,然后將讀取到的ApplicationContextInitializer類型的類實(shí)例化
    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 4.加載所有監(jiān)聽(tīng)器,這里與上面類似也調(diào)用this.getSpringFactoriesInstances(),但是由于之前已經(jīng)把spring.factries文件讀取到緩存中了,因此不用再次讀取文件而是讀緩存
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    // 5.設(shè)置程序運(yùn)行的主類MainApplication,以便后面執(zhí)行run方法
    this.mainApplicationClass = this.deduceMainApplicationClass();
}
2.確定應(yīng)用程序類型
// 提供三種類型
// 1.NONE 表示當(dāng)前的應(yīng)用既不是一個(gè)web應(yīng)用也不是一個(gè)reactive應(yīng)用,是一個(gè)純后臺(tái)的應(yīng)用。不啟動(dòng)內(nèi)嵌的服務(wù)
// 2.SERVLET 當(dāng)前應(yīng)用是一個(gè)基于servlet API的標(biāo)準(zhǔn)的web應(yīng)用,需啟動(dòng)內(nèi)嵌servlet web服務(wù)
// 3.REACTIVE 是spring5當(dāng)中的新特性,表示是一個(gè)響應(yīng)式的web應(yīng)用,需啟動(dòng)內(nèi)嵌的響應(yīng)式web服務(wù)
this.webApplicationType = WebApplicationType.deduceFromClasspath();

// 這里實(shí)際上是根據(jù)類加載器名字具體是哪一種,本項(xiàng)目中SERVLET_INDICATOR_CLASSES為['javax.servlet.Servlet', 'org.springframework.web.context.ConfigurableWebApplicationContext']
// ClassUtils.isPresent()方法,判斷指定類名的類是否存在,是否可以進(jìn)行加載(如果我們導(dǎo)入了,相對(duì)應(yīng)的jar包,就可以加載,如果沒(méi)有導(dǎo)入就不能加載)
// 如果能夠加載DispatcherHandler類,但是無(wú)法加載DispatcherServlet和ServletContainer類,就證明是一個(gè)響應(yīng)式web應(yīng)用
static WebApplicationType deduceFromClasspath() {
    // 判斷能否加載響應(yīng)式web應(yīng)用
    if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
        return REACTIVE;
    } else {
        String[] var0 = SERVLET_INDICATOR_CLASSES;
        int var1 = var0.length;

        for(int var2 = 0; var2< var1; ++var2) {
            String className = var0[var2];
            // 判斷能否加載SERVLET_INDICATOR_CLASSES里的兩個(gè)類名
            if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
                return NONE;
            }
        }

        return SERVLET;
    }
}

// 補(bǔ)充ClassUtils.isPresent()方法  實(shí)際上是調(diào)用forName來(lái)獲取類加載器
public static boolean isPresent(String className, @Nullable ClassLoader classLoader) {
    try {
        forName(className, classLoader);
        return true;
    } catch (IllegalAccessError var3) {
        throw new IllegalStateException("Readability mismatch in inheritance hierarchy of class [" + className + "]: " + var3.getMessage(), var3);
    } catch (Throwable var4) {
        return false;
    }
}
3.加載所有初始化器,獲取spring工廠文件中的實(shí)例

補(bǔ)充說(shuō)明,4.加載監(jiān)聽(tīng)器與下面流程基本一致,不同的是3.加載所有初始化器時(shí)讀取的一些文件配置會(huì)放入緩存中,加載監(jiān)聽(tīng)器時(shí)從緩存讀取數(shù)據(jù)即可。

this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

privateCollectiongetSpringFactoriesInstances(Classtype) {
    // type為ApplicationContextInitializer.class
    return this.getSpringFactoriesInstances(type, new Class[0]);
}

privateCollectiongetSpringFactoriesInstances(Classtype, Class[] parameterTypes, Object... args) {
    // 獲取SpringApplication的類加載器,這里是一個(gè)系統(tǒng)類加載器AppClassLoader
    ClassLoader classLoader = this.getClassLoader();
    // 加載spring.factories文件中的類的全類名集合
    Setnames = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 通過(guò)反射獲取到集合中全類名對(duì)應(yīng)的Class,并創(chuàng)建其實(shí)例對(duì)象,返回實(shí)例對(duì)象
    Listinstances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 根據(jù)優(yōu)先級(jí)排序
    AnnotationAwareOrderComparator.sort(instances);
    // 返回實(shí)例
    return instances;
}

public static ListloadFactoryNames(ClassfactoryType, @Nullable ClassLoader classLoader) {
    // 加載初始化器時(shí)factoryTypeName="org.springframework.context.ApplicationContextInitializer",對(duì)應(yīng)之前設(shè)置的ApplicationContextInitializer.class
    // 加載監(jiān)聽(tīng)器時(shí)factoryTypeName="org.springframework.context.ApplicationListener",對(duì)應(yīng)ApplicationListener.calss
    String factoryTypeName = factoryType.getName();
    // 正式加載spring-boot包里META-INF目錄下的spring.factories文件
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

// loadSpringFactories()才正式去加載spring-boot包里META-INF目錄下的spring.factories文件
private static Map>loadSpringFactories(@Nullable ClassLoader classLoader) {
    // 這里是讀緩存,加載初始化器時(shí)還沒(méi)有緩存(在這一環(huán)節(jié)添加了緩存),到加載監(jiān)聽(tīng)器時(shí)就能從緩存讀取數(shù)據(jù)了
    MultiValueMapresult = (MultiValueMap)cache.get(classLoader);
    if (result != null) {
        return result;
    } else {
        try {
            // 獲取當(dāng)前項(xiàng)目中所有META-INF/spring.factories文件的絕對(duì)路徑,對(duì)于目前使用的項(xiàng)目則是讀取下面的路徑,因?yàn)槭菧y(cè)試項(xiàng)目,因此引入的包和版本比較雜亂
            // file:/E:/javaDevelopmentTools/maven/repository/org/springframework/boot/spring-boot/2.3.12.RELEASE/spring-boot-2.3.12.RELEASE.jar!/META-INF/spring.factories
            // file:/E:/javaDevelopmentTools/maven/repository/org/springframework/spring-beans/5.2.15.RELEASE/spring-beans-5.2.15.RELEASE.jar!/META-INF/spring.factories
                      //   file:/E:/javaDevelopmentTools/maven/repository/org/mybatis/spring/boot/mybatis-spring-boot-autoconfigure/2.0.1/mybatis-spring-boot-autoconfigure-2.0.1.jar!/META-INF/spring.factories
            //  file:/E:/javaDevelopmentTools/maven/repository/com/baomidou/mybatis-plus-boot-starter/3.5.1/mybatis-plus-boot-starter-3.5.1.jar!/META-INF/spring.factories
                       //    file:/E:/javaDevelopmentTools/maven/repository/org/springframework/boot/spring-boot-autoconfigure/2.3.12.RELEASE/spring-boot-autoconfigure-2.3.12.RELEASE.jar!/META-INF/spring.factories
            // 這里貼一下pom.xml文件的部分引用Enumerationurls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            LinkedMultiValueMap result = new LinkedMultiValueMap();

            // 遍歷上面獲取到的絕對(duì)路徑
            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                // 把文件資源加載到Properties中
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                Iterator var6 = properties.entrySet().iterator();

                while(var6.hasNext()) {
                    Entryentry = (Entry)var6.next();
                    String factoryTypeName = ((String)entry.getKey()).trim();
                    String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                    int var10 = var9.length;

                    for(int var11 = 0; var11< var10; ++var11) {
                        String factoryImplementationName = var9[var11];
                        // K-V形式,把spring.factories中的的類型,下面圖例中會(huì)貼上result的內(nèi)容
                        result.add(factoryTypeName, factoryImplementationName.trim());
                    }
                }
            }

            // 將類加載器加載的spring.factories文件結(jié)果集放入緩存
            cache.put(classLoader, result);
            return result;
        } catch (IOException var13) {
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
        }
    }
}

并且貼一下對(duì)應(yīng)圖片,下圖為result.add(factoryTypeName, factoryImplementationName.trim());后的result。大多是與項(xiàng)目啟動(dòng)、異常處理、自動(dòng)配置等基礎(chǔ)配置相關(guān)的內(nèi)容。

下面則是讀取了哪些spring.factories文件(實(shí)際項(xiàng)目中會(huì)很多,這里只是測(cè)試項(xiàng)目)

三 執(zhí)行run方法

下面貼一下主要代碼部分

public ConfigurableApplicationContext run(String... args) {
    // 開(kāi)啟計(jì)時(shí)器。計(jì)算程序啟動(dòng)時(shí)間用的
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    // 6.開(kāi)啟java的headless模式 是SpringApplication的 this.headless = true;控制的
    this.headless = true;
    // 保證headless一定有值
    this.configureHeadlessProperty();
    // 7.獲取并啟用監(jiān)聽(tīng)器 這里獲取到的是SpringApplicationRunListeners對(duì)象,里面有之前初始化SpringApplication時(shí)的監(jiān)聽(tīng)器
    // args默認(rèn)為空,我填寫(xiě)了--server.port=8079屬性
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting();

    try {
        // 8.設(shè)置應(yīng)用程序參數(shù)
        // 初始化ApplicationArguments對(duì)象,提供訪問(wèn)運(yùn)行SpringApplication時(shí)的參數(shù)
        // 由于之前的配置 args 里帶有--server.port=8079參數(shù),而這個(gè)參數(shù)就會(huì)被封裝進(jìn)Source對(duì)象,底層是Spring 框架的 SimpleCommandLinePropertySource
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 9.準(zhǔn)備環(huán)境變量 參數(shù)是監(jiān)聽(tīng)器和應(yīng)用程序參數(shù)
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        // 忽略掉部分bean信息
        this.configureIgnoreBeanInfo(environment);
        // 打印banner信息 這里實(shí)際上是打印了Spring的標(biāo)志
        Banner printedBanner = this.printBanner(environment);
        // 10.創(chuàng)建應(yīng)用程序的上下文
        context = this.createApplicationContext();
        // 10.準(zhǔn)備上下文環(huán)境
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 11.刷新上下文,屬于Spring的范疇(自動(dòng)裝配+啟動(dòng)tomcat)
        this.refreshContext(context);
        // 11.刷新上下文后置處理(目前是空的)
        this.afterRefresh(context, applicationArguments);
        // 停止計(jì)時(shí)器
        stopWatch.stop();
                //  打印JVM的啟動(dòng)和運(yùn)行信息,啟動(dòng)類、java版本等 this.logStartupInfo = true;
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }

        // 創(chuàng)建應(yīng)用上下文啟動(dòng)完成事件對(duì)象ApplicationStartedEvent
        // 發(fā)布應(yīng)用上下文啟動(dòng)完成事件,廣播事件,調(diào)用監(jiān)聽(tīng)器相對(duì)應(yīng)的監(jiān)聽(tīng)方法
        listeners.started(context);
        this.callRunners(context, applicationArguments);
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, listeners);
        throw new IllegalStateException(var9);
    }


    try {
        // 12.發(fā)布上下文準(zhǔn)備就緒事件
        listeners.running(context);
        return context;
    } catch (Throwable var8) {
        this.handleRunFailure(context, var8, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var8);
    }
}
7.獲取并啟用監(jiān)聽(tīng)器 9.準(zhǔn)備環(huán)境變量 9.1ConfigurableEnvironment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    // 創(chuàng)建或者返回環(huán)境
    ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        // 配置環(huán)境
    this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach((Environment)environment);
    // 監(jiān)聽(tīng)器的環(huán)境準(zhǔn)備,這部分.class文件斷點(diǎn)匹配不上,但是從輸出上看多了initialMulticaster
    listeners.environmentPrepared((ConfigurableEnvironment)environment);
    // 把環(huán)境綁定到SpringApplication
    this.bindToSpringApplication((ConfigurableEnvironment)environment);
    // 之前配置的 this.isCustomEnvironment = false;
    if (!this.isCustomEnvironment) {
        environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
    }

    ConfigurationPropertySources.attach((Environment)environment);
    // 返回的environment環(huán)境信息不僅僅是SpringBoot項(xiàng)目本身的,虛擬機(jī)、項(xiàng)目運(yùn)行系統(tǒng)信息(Linux/Windows等)、JDK、MAVEN等信息也包含其中
    return (ConfigurableEnvironment)environment;
}

// 由于沒(méi)有設(shè)置environment,因此根據(jù)this.webApplicationType = WebApplicationType.deduceFromClasspath();得知為SERVLET
private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
        return this.environment;
    } else {
        switch(this.webApplicationType) {
        case SERVLET:
            return new StandardServletEnvironment();
        case REACTIVE:
            return new StandardReactiveWebEnvironment();
        default:
            return new StandardEnvironment();
        }
    }
}

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    // 之前設(shè)置的this.addConversionService = true;加載默認(rèn)的類型轉(zhuǎn)換和格式化類
    if (this.addConversionService) {
        ConversionService conversionService = ApplicationConversionService.getSharedInstance();
        environment.setConversionService((ConfigurableConversionService)conversionService);
    }

    // 配置environment的PropertySources
    this.configurePropertySources(environment, args);
    // 配置environment的ActiveProfiles
    this.configureProfiles(environment, args);
}
9.2忽略Bean的BeanInfo信息
// spring.beaninfo.ignore默認(rèn)為true表示跳過(guò)對(duì)BeanInfo類的搜索
// 忽略所有自定義的BeanInfo信息的搜索
// 通過(guò)Java的Introspector.getBeanInfo方法,可以獲取到JavaBean的BeanInfo信息(一般有Bean的方法、屬性、類相關(guān)信息等)
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());
    }
}
9.3打印banner信息

這里實(shí)際上是打印了Spring的標(biāo)志

private Banner printBanner(ConfigurableEnvironment environment) {
    // 之前設(shè)置的this.bannerMode = Mode.CONSOLE;
    if (this.bannerMode == Mode.OFF) {
        return null;
    } else {
        ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader((ClassLoader)null);
        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);
    }
}

console控制臺(tái)會(huì)打印出下面標(biāo)識(shí)(默認(rèn)輸出,可以通過(guò)配置修改)

10.創(chuàng)建應(yīng)用程序的上下文 10.1ConfigurableApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
    ClasscontextClass = this.applicationContextClass;
    if (contextClass == null) {
        try {
            // 根據(jù)Web應(yīng)用類型創(chuàng)建對(duì)應(yīng)的上下文,目前項(xiàng)目這里根據(jù)之前的配置 是SERVLET
            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);
        }
    }
    
        // 實(shí)例化應(yīng)用上下文
    return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
10.2準(zhǔn)備上下文環(huán)境
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    // 把之前的配置的環(huán)境加載到應(yīng)用上下文中
    context.setEnvironment(environment);
    // 實(shí)例化單例的beanName生成器
    this.postProcessApplicationContext(context);
    // 遍歷之前在SpringApplication中的初始化器,進(jìn)行初始化
    this.applyInitializers(context);
    // 監(jiān)聽(tīng)器初始化
    listeners.contextPrepared(context);
    // 打印JVM的啟動(dòng)和運(yùn)行信息,啟動(dòng)類、java版本等 this.logStartupInfo = true;
    if (this.logStartupInfo) {
        this.logStartupInfo(context.getParent() == null);
        this.logStartupProfileInfo(context);
    }

    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    // 將啟動(dòng)參數(shù)注冊(cè)到容器中
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }

    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }

    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }

    Setsources = this.getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    this.load(context, sources.toArray(new Object[0]));
    listeners.contextLoaded(context);
}


protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
    if (this.beanNameGenerator != null) {
        context.getBeanFactory().registerSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator", this.beanNameGenerator);
    }

    if (this.resourceLoader != null) {
        if (context instanceof GenericApplicationContext) {
            ((GenericApplicationContext)context).setResourceLoader(this.resourceLoader);
        }

        if (context instanceof DefaultResourceLoader) {
            ((DefaultResourceLoader)context).setClassLoader(this.resourceLoader.getClassLoader());
        }
    }
    // 加載默認(rèn)的類型轉(zhuǎn)換和格式化類 this.addConversionService = true;
    if (this.addConversionService) {
        // 設(shè)置beanFactory的conversionService屬性
        context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
    }
}

// 執(zhí)行初始化方法
protected void applyInitializers(ConfigurableApplicationContext context) {
    Iterator var2 = this.getInitializers().iterator();

    while(var2.hasNext()) {
        ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
        ClassrequiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        initializer.initialize(context);
    }
}11.刷新上下文(這部分會(huì)調(diào)用Spring里的代碼,包括自動(dòng)裝配Tomcat)
private void refreshContext(ConfigurableApplicationContext context) {
    // 之前設(shè)置的this.registerShutdownHook = true;創(chuàng)建線程,該線程用來(lái)在java程序關(guān)閉后釋放資源
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        } catch (AccessControlException var3) {
        }
    }
    this.refresh((ApplicationContext)context);
}

上面的this.refresh((ApplicationContext)context);其實(shí)就在調(diào)用Spring相關(guān)包了

public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        // 刷新前準(zhǔn)備工作,設(shè)置了容器的啟動(dòng)時(shí)間、加載environment對(duì)象、準(zhǔn)備監(jiān)聽(tīng)器等
        this.prepareRefresh();
        // 獲取BeanFactory,類型是DefaultListableBeanFactory
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        // 把配置和屬性信息填充到beanFactory中
        this.prepareBeanFactory(beanFactory);

        try {
            // 
            this.postProcessBeanFactory(beanFactory);
            this.invokeBeanFactoryPostProcessors(beanFactory);
            // 注冊(cè)BeanPostProcessor(初始化時(shí)才會(huì)調(diào)用)
            this.registerBeanPostProcessors(beanFactory);
            // 初始化MessageSource組件,消息處理相關(guān)
            this.initMessageSource();
            // 事件廣播相關(guān)
            this.initApplicationEventMulticaster();
            // 具體由子類實(shí)現(xiàn),根據(jù)Spring容器的種類進(jìn)行不同的事情處理.
            this.onRefresh();
            // 注冊(cè)引用的監(jiān)聽(tīng)器
            this.registerListeners();
            // 實(shí)例非懶加載的單例
            this.finishBeanFactoryInitialization(beanFactory);
            // 完成刷新并進(jìn)行通知廣播
            this.finishRefresh();
        } catch (BeansException var9) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
            }

            this.destroyBeans();
            this.cancelRefresh(var9);
            throw var9;
        } finally {
            this.resetCommonCaches();
        }
    }
}
11.1beanFactory

ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();這部分

11.2this.onRefresh();

根據(jù)不同Spring容器來(lái)的創(chuàng)建不同容器

// 項(xiàng)目時(shí)web項(xiàng)目,用的ServletWebServerApplicationContext
// 對(duì)應(yīng)代碼如下,由this.createWebServer();創(chuàng)建具體的Servlet容器
protected void onRefresh() {
    super.onRefresh();

    try {
        // 由于SpringBoot內(nèi)置Tomcat容器,所以這里實(shí)際上會(huì)創(chuàng)建一個(gè)TomcatServletWebServerFactory生成TomcatWebServer
        this.createWebServer();
    } catch (Throwable var2) {
        throw new ApplicationContextException("Unable to start web server", var2);
    }
}

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前標(biāo)題:SpringBoot啟動(dòng)流程-創(chuàng)新互聯(lián)
URL分享:http://www.rwnh.cn/article6/csepig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站營(yíng)銷(xiāo)搜索引擎優(yōu)化、建站公司、網(wǎng)站設(shè)計(jì)、網(wǎng)站設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

德令哈市| 哈巴河县| 沧州市| 武安市| 涿鹿县| 上饶市| 昌平区| 松江区| 泌阳县| 锡林郭勒盟| 简阳市| 康马县| 庆元县| 于都县| 东兴市| 大港区| 泸溪县| 兴化市| 容城县| 城口县| 永城市| 肇州县| 渝北区| 石楼县| 白水县| 靖远县| 奉新县| 石狮市| 安泽县| 青河县| 进贤县| 鄂伦春自治旗| 平和县| 南江县| 金秀| 安义县| 沙湾县| 彰化市| 南部县| 江川县| 探索|