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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容