spring基础学习(1)

Spring框架主要构成

  • Spring框架主要有7个模块:
    1.Spring AOP:面向切面编程思想,同时也提供了事务管理。
    2.Spring ORM:提供了对Hibernate、myBatis的支持。
    3.Spring DAO:提供了 对Data Access Object模式和JDBC的支持。实现业务逻辑与数据库访问代码分离,降低代码耦合度。
    4.Spring Web:提供了Servlet监听器的Context和Web应用的上下文。
    5.Spring Context:提供了Spring上下文环境,以及其他如国际化、Email等服务。
    6.Spring MVC:提供了MVC设计模式的实现。
    7.Spring core:提供了Spring框架基本功能(IOC功能),如BeanFactory以工厂模式创建所需对象、通过读取xml文件实例化对象、管理组件生命周期等。


    体系结构1.png

    体系结构2.png

SpringBoot框架的优点

1.快速构建专案。
2.对主流开发框架的无配置整合。
3.专案可独立执行,无须外部依赖Servlet容器。
4.提供执行时的应用监控。
5.极大的提高了开发、部署效率。
6.与云端计算的天然整合。


image.png

Spring Boot的主要执行流程

  • 初始化Spring Application实例
  • 初始化Spring Boot项目启动


    启动流程示意图
源码角度分析流程
  1. 项目启动文件,入口就是这个main方法,@SpringBootApplication注解的作用下文有写到,这里不做赘述。
    启动文件.png
  2. 跟踪进入run方法,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例的run方法。
    image.png
  3. 先看一下创建的实例的构造函数,发现构造函数进行了重载,
    271行推断了web的应用类型,272行加载上下文初始化器,273行加载应用的事件监听器,274行推断引导类
    image.png

    3.1web应用的类型推断
    根据WebApplicationType这个类的静态方法deduceFromClasspath()推断Web应用类型,其实也就是根据当前的应用 ClassPath 中是否存在相关实现类来推断 Web 应用的类型,类型有三种:
  • Web Reactive: WebApplicationType.REACTIVE
  • Web Servlet: WebApplicationType.SERVLET
  • 非 Web: WebApplicationType.NONE
    判断当前class loader中是否存在对应的类型.png
  • 根据上面的代码可以看出推断的逻辑:
    • 当WEBFLUX_INDICATOR_CLASS存在并且WEBMVC_INDICATOR_CLASS和JERSEY_INDICATOR_CLASS都不存在的时候,Web的类型才会被推断成Web Reactive。
    • 当WEBFLUX_INDICATOR_CLASS和SERVLET_INDICATOR_CLASSES都不存在的时候,Web的类型才会被推断成非 Web类型。
    • 其它情况都会被推断成Web Servlet的类型,所以当Reactive和Servlet同时存在的时候,Reactive会被覆盖掉。

3.2加载应用上下文初始化器
利用 Spring 工厂加载机制,实例化 ApplicationContextInitializer 实现类,并排序对象集合。

image.png

3.3加载应用事件监听器
利用 Spring 工厂加载机制,实例化 ApplicationListener 实现类,并排序对象集合。其实这个和上下文的初始化器的加载时同样的原理。
image.png

3.4推断引导类
利用异常的堆栈信息来推断引导类,也就是我们启动Spring Boot项目的那个main方法所在的类。
image.png

通过异常的堆栈信息中方法名为main的栈帧来得到入口类的名字。
到这里SpringApplication就已经完成了在构造阶段所初始化的过程。

  1. 探究SpringApplication的运行阶段
    当我们执行完new SpringApplication(primarySources)后,就会调用该对象的run方法。

 public ConfigurableApplicationContext run(String... args) {
        // 启动一个计时器
        StopWatch stopWatch = new StopWatch();
        // 开始计时
        stopWatch.start();
        // 定义局部变量
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        // 设置java.awt.headless系统属性为true - 没有图形化界面
        configureHeadlessProperty();
        // 1、加载SpringApplication运行监听器
        SpringApplicationRunListeners listeners = getRunListeners(args);
        // 2、运行SpringApplication运行监听器,Spring应用刚启动
        listeners.starting();
        try {
            // 根据传入的args,创建ApplicationArguments对象
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            // 4、创建 Environment,这里调用listeners.environmentPrepared(ConfigurableEnvironment)
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
            // 打印Banner
            Banner printedBanner = printBanner(environment);
            // 5、创建Spring应用上下文
            context = createApplicationContext();
            // 异常分析报告的记录容器的初始化
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            // Spring上下文前置处理,这里调用listeners.contextPrepared(context)和listeners.contextLoaded(context)
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
            // Spring上下文刷新
            refreshContext(context);
            // Spring上下文后置处理
            afterRefresh(context, applicationArguments);
            // 停止计时
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass)
                        .logStarted(getApplicationLog(), stopWatch);
            }
            // Spring 应用已经启动
            listeners.started(context);
            callRunners(context, applicationArguments);
        }
        catch (Throwable ex) {
            // 处理异常,并会打印异常分析报告,并调用listeners.failed(context, exception);
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }

        try {
            // Spring 应用正在运行
            listeners.running(context);
        }
        catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }

总结

至此我们就完成了对Spring Boot项目启动的流程进行了简要的分析。我们可以知道SpringApplication主要分为两个阶段,一个是准备阶段主要进行Web类型推断、引导类推断、加载上下文初始化器和事件监听器,另一个是运行阶段主要进行加载运行SpringApplication的运行监听器、监听Spring Boot事件、创建Environment、创建Spring应用上下文。这样就完成了一个Spring Boot应用的启动。


Spring Boot自动配置的基础知识和原理

配置文件能配置的属性参照(https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties

自动配置原理

通过注解@SpringBootApplication,SpringBoot启动时加载主配置类,开启了自动配置功能@EnableAutoConfiguration

image.png

  • @SpringBootConfiguration:表面这是个配置类,开发者可以在这个类中配置Bean,类似Spring中的applicationContext.xml的角色
  • @EnableAutoConfiguration:开启自动化配置,开发者可以使用自定义配置代替自动化配置。
  • @ComponentScan:完成包扫描,默认扫描的类都位于当前类所在的包下面,所以项目启动类务必放在根包中,否则可能出现扫描不到的情况。
多环境配置
  • 配置文件命名
    • application-{profile}.properties
    • profile对应环境标志
    • dev:开发环境
    • prod:生产环境
  • 环境加载
    • 由application.properties文件中的spring.profiles.active属性设置


      配置图片.png
配置原理
  • Spring Boot应用可以编写多个配置类,使用@Configuration标志;
  • Spring Boot会将其汇集起来构建出一个完整的运行时环境。


    配置原理示意图.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容