欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Springboot 原理篇(一)

程序员文章站 2024-03-24 17:41:46
...
    相信Springboot使用的越来越广泛了,约定大于配置,对于开发者使用确实是方便了,但是Springboot底层的原理清楚吗?下 
    面从源码一步一步来揭秘Springboot

    从Springboot入口Main函数分析
    public static void main(String[] args) {
        SpringApplication.run(XlbstudyApplication.class, args);
    }
    ···debug···
        public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
        return new SpringApplication(sources).run(args);
    }
    我们可以看到 new SpringApplication(sources).run(args) 
    重点:第一步 new SpringApplication
        private void initialize(Object[] sources) {
        if (sources != null && sources.length > 0) {
            //保存配置类
            this.sources.addAll(Arrays.asList(sources));
        }
        //判断是否是Web环境
        this.webEnvironment = deduceWebEnvironment();
        //重点  主要内容:从 META-INF/spring.factories 加载Initializers 
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
        //重点  主要内容:从 META-INF/spring.factories 加载Listeners
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //选择 有main函数入口的配置类
        this.mainApplicationClass = deduceMainApplicationClass();
    }

    我们随便打开一个spring.factories文件看看 
    # Initializers
    org.springframework.context.ApplicationContextInitializer=\
    org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
    org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

    # Application Listeners
    org.springframework.context.ApplicationListener=\
    org.springframework.boot.autoconfigure.BackgroundPreinitializer


    重点: 第二步 run  
    run方法的代码如下
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch(); //这个就不解释了
        stopWatch.start();
        //定义一个ioc容器
        ConfigurableApplicationContext context = null;
        //定义一个失败分析器,用于异常分析的 
        FailureAnalyzers analyzers = null;
        //点进去可以发现是配置awt的 对我们正常的开发web应用没什么卵用
        configureHeadlessProperty();
        //重点 获取listener ,我们从第一步可以看到加载了listener 
        SpringApplicationRunListeners listeners = getRunListeners(args);
        //重点 回调 listenr的start方法
        listeners.starting();
        try {
            //包装web容器参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            //重点 准备环境变量 分析里面代码:listeners.environmentPrepared(environment);
            //回掉 listeners的 environmentPrepared 方法
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            //打印Banner 没卵用
            Banner printedBanner = printBanner(environment);
            //初始化 ioc容器
            context = createApplicationContext();
            //初始化
            analyzers = new FailureAnalyzers(context);
            /*重点 准备上下文容器: 
             *   回调初始化器
             *   initializer.initialize(context);
             *   回调 listener
             *   listeners.contextPrepared(context);
             */
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
            /* 
             * 重中之重  spring ioc容器初始化,加载Spring bean 这个我们单独抽出来在讲重点会讲 
             * BeanPostProcessor后置处理器,其实xxAware ,@Autoword... 原理就是BeanPostProcessor
             * 后面我们在讲
             */
            refreshContext(context);
            /*
             * ioc容器初始化完成后 ,回调ApplicationRunner CommandLineRunner的run方法
             *  callRunner((ApplicationRunner ) runner, args);
             *  callRunner((CommandLineRunner) runner, args);
             */
            afterRefresh(context, applicationArguments);
            /*
             * 回调listener 的 finished方法
             */
            listeners.finished(context, null);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
            return context;
        }
        catch (Throwable ex) {
            handleRunFailure(context, listeners, analyzers, ex);
            throw new IllegalStateException(ex);
        }
    }

    总结:从上面的代码我们可以看到 Springboot为我们提供了4个组件 供我们扩展使用
    ApplicationContextInitializer
    ApplicationListener
    ApplicationRunner
    CommandLineRunner
    至于什么情况下会回调上面的组件 上诉源码写的很清楚了。但是核心的原理关键还是在refreshContext
    下面章节重点会讲解refreshContext,通过refreshContext源码可以知道Spring 扩展的原理,springboot 各种注解如 
    何实现,以及Springboot-start如何实现的

转载于:https://my.oschina.net/xliangbo/blog/2253903