Java | 详解Spring Boot关键知识点

旨在通过设计大量的自动化配置等方式来简化Spring 原有样板化的配置,使得开发者可以快速构建应用。

1 介绍

Spring Boot,从本质上将,其实就是spring,它代替我们做了那些以往需要我们自己做的Spring Bean配置。

Spring-boot并没有引入任何形式的代码生成。而是利用了Spring 4的条件化配置特性,以及Maven和gradle提供的传递依赖解析,以实现Spring-boot中的自动配置。

Spring Boot可以把Web应用程序变为可执行的jar文件,而不用部署到传统的Java应用服务器中,就能在命令行中执行。

实现的原理是spring-boot中嵌套了一个Servlet容器(如Tomcat),这是内嵌的Servlet容器提供的功能,并不是Spring-boot实现的。

2 简单的demo

2.1 创建工程

  • 目录结构图
    Java | 详解Spring Boot关键知识点_第1张图片

  • spring initializr初始化项目
    Java | 详解Spring Boot关键知识点_第2张图片

  • pom文件内容
    Java | 详解Spring Boot关键知识点_第3张图片

2.2 目录结构

Spring Boot 的基础结构有三大块:

src/main/java : 主程序入口DemoAppication ,可以通过直接运行该类来启动SPring Boot应用。

src/main/resources:配置目录,该目录用来存放y应用的一些配置信息,比如应用名、服务端口、数据库链接等。引入了web模块,因此会产生static目录与templates目录,前者用于存放静态资源,如图片、CSS文件、JavaScript等;后者用于存放Web页面的模板文件。

src/test/:单元测试目录,生成的DemoApplication通过Junit4实现,可以直接运行的Spring Boot 应用的测试。

3 自动配置

对于很多针对spring应用程序的常见功能,spring boot 能自动提供相关配置。

简单点理解就是可以省略我们在使用spring时的大量配置文件。

3.1 详情简介

SpringBoot利用Spring 4.0提供的条件化配置支持,实现了自动配置。其它应用样例如下:

1:因为Classpath里有H2,所以会创建一个嵌入式的H2数据库Bean,类型为javax.sql.DataSource,JPA实现(Hibernate)需要它来访问数据库;

2:因为Classpath里有Hibernate(Spring Data JPA传递引入的)的实体管理器,所以自动配置会配置与Hibernate相关的Bean,包括Spring的LocalContainerEntityManagerFactoryBean和JpaVendorAdapter;

3:因为Classpath里有SpringDataJPA,所以它会自动配置为根据数据库的接口创建仓库实现;

4:因为Classpath里有Thymeleaf,所以Thymeleaf会配置为SpringMVC的视图,包括一个Thymeleaf的模板解析器、模板引擎及视图解析器。视图解析器会解析相对于Classpath根目录的 /templates目录里的模板;

5:因为Classpath里有SpringMVC(归功于Web起步依赖),所以会配置Spring的DispatcherServlet并启动SpringMVC;

6:因为这是一个Spring MVC Web应用程序,所以会注册一个资源处理器,把相对于Classpath根目录的 /static目录里的静态资源提供出来(还能处理 /public、/resources和 /META-INF/resources的静态内容);

7:因为Classpath里有Tomcat,所以会启动一个嵌入式的Tomcat容器,监听8080端口(默认)。

Spring Boot自动配置承担起了配置Spring的重任,开发者只需专注于自己的应用程序即可。

3.2 实现原理

自动配置,说到底也就是基于spring 4.0的条件化配置,或者说就是利用条件化配置。

以安全配置为例,如果我们没有自定义安全配置的话,如果我们使用了相关注解如@EnableWebSecurity,便会使用默认的安全配置。

如果是我们使用了自定义配置的话则默认的安全配置就会被覆盖。

其中最关键的一个类是SpringBootWebSecurityConfiguration.这个类用了多个注解,其中实现自动配置最关键的一个注解就是@ConditionalOnMissingBean(WebSecurityConfiguration.class);

这个注解的意思是我们这个类要在没有WebSecurityConfiguration这个bean的条件下才会创建。

而在我们自定义安全配置的时候需要自定义类并继承WebSecurityConfigurerAdapter,而这个类是实现了WebSecurityConfigurer接口。

@ConditionalOnMissingBean注解要求当下没有WebSecurityConfiguration类型的 Bean。虽然表面上我们并没有这么一个Bean,但通过在自定义的SecurityConfig上添加@EnableWeb-Security注解,我们实际上间接创建了一个WebSecurityConfiguration Bean。所以在自动 配置时,这个Bean就已经存在了,@ConditionalOnMissingBean条件不成立,SpringBoot- WebSecurityConfiguration提供的配置就被跳过了。

3.3 条件化注解

条件化注解:

条件化注解即配置生效条件 @ConditionalOnBean 配置了某个特定Bean

@ConditionalOnMissingBean 没有配置特定的Bean

@ConditionalOnClass Classpath里有指定的类

@ConditionalOnMissingClass Classpath里缺少指定的类

@ConditionalOnExpression 给定的Spring Expression

Language(SpEL)表达式计算结果为true

@ConditionalOnJava Java的版本匹配特定值或者一个范围值

@ConditionalOnJndi 参数中给定的JNDI位置必须存在一个,如果没有给参数,则要有JNDI InitialContext

@ConditionalOnProperty 指定的配置属性要有一个明确的值

@ConditionalOnResource Classpath里有指定的资源

@ConditionalOnWebApplication 这是一个Web应用程序

@ConditionalOnNotWebApplication 这不是一个Web应用程序

3.4 从数据源获取属性的几种方式

关于几种方式的优先级设置:

这个列表按照优先级排序,也就是说,任何在高优先级属性源里设置的属性都会覆盖低优先 级的相同属性。例如,命令行参数会覆盖其他属性源里的属性。

application.properties和application.yml文件能放在以下四个位置。

(1) 外置,在相对于应用程序运行目录的/config子目录里。

(2) 外置,在应用程序运行的目录里。

(3) 内置,在config包内。

(4) 内置,在Classpath根目录。 同样,这个列表按照优先级排序。

也就是说,/config子目录里的application.properties会覆盖 应用程序Classpath里的application.properties中的相同属性。

此外,如果你在同一优先级位置同时有application.properties和application.yml,那么application. yml里的属性会覆盖application.properties里的属性。

  • 命令行参数
  • java:comp/env里的JNDI属性
  • JVM系统属性
  • 操作系统环境变量
  • 随机生成的带random.*前缀的属性
  • 应用程序以外的application.properties或者appliaction.yml文件
  • 打包在应用程序内的application.properties或者appliaction.yml文件
  • 通过@PropertySource标注的属性源
  • 默认属性

3.5 自动配置微调

  • 禁用模板缓存

    禁用模板缓存:

    首先以thymeleaf模板为例.

    有时候我们的程序做了修改,需要重启应用否则对thymeleaf模板的变更不会生效,这是因为thymeleaf默认缓存,这有助于改善应用程序的性能,但是在我们开发过程中确实不太方便,无法实时看到变更的效果。

    只需要经spring.thymeleaf.cache设置为false就能够禁用thymelead模板缓存了。

    命令行参数方式:

    $ java -jar readinglist-0.0.1-SNAPSHOT.jar --spring.thymeleaf.cache=false

    这条命令中的readinglist根据实际项目名称变化;

    如果希望每次运行时都禁用缓存,可以创建一个application.yml,包含内容:

      spring:   
    
          thymeleaf:     
    
                cache: false 
    

    注意发布在正式环境时更改文件。否则生产环境里的应用程序就无法享受模板缓 存带来的性能提升了。

    当然,在application.properties文件中配置也是一样可以的;

      spring.thymeleaf.cache=false.
    

    除了使用Thymeleaf作为应用程序的视图,Spring Boot支持的其他模板也能关闭模板缓存, 设置这些属性就好了:  spring.freemarker.cache(Freemarker)  spring.groovy.template.cache(Groovy模板)  spring.velocity.cache(Velocity)

    默认情况下,这些属性都为true,也就是开启缓存。将它们设置为false即可禁用缓存

  • 配置嵌入式服务器

    server.port

    设置方式和上一个类似,只是设置的参数名不同。

    可参考:spring-boot实战51页。

  • 配置日志

    日志配置,默认情况下spring-boot都是默认十四用logback记录日志的。用其他日志实现替代LogBack,一般来并不需要切换日志实现.如果是需要使用其他的,只需要修改依赖,引入对应日志的起步依赖,同时排除掉LogBack即可。

4 起步依赖

告诉spring boot需要什么功能,它就能引入需要的库。

就比如应用是个Web程序,所以加入web的起步依赖(spring-boot-started-web),仅此一个,他会根据依赖传递把其他需要的依赖都自动添加进来,而并不需要我们手动一个个加入各种依赖。

实际上可以理解为添加了web的起步依赖,就指定了应用程序所需的一类功能。

如果是应用程序使用到JPA持久化,那我们只需要添加jpa的起步依赖就可以了。

Spring Boot起步依赖基本都以spring-boot-starter打头,随后是直接代表其功能的名字,比如web、test。

起步依赖引入的库的版本都是经过了测试的,所以不用担心版本冲突的问题。

4.1 Spring-boot-starter-web

全栈Web开发模块,包含嵌入式Tomcat、Spring MVC.

这里引用的web和test模块,在Spring Boot生态中被称为Starter POMs. Starter POMs是一系列轻便的依赖包,是一套一站式的Spring相关技术的解决方案。开发者在使用和整合模块时,不必再去搜寻各种依赖配置来使用,只需要引用对应的模板包即可。比如开发web应用的时候,那就引入spring-boot-starter-web,希望应用具备访问数据库能力,那就再引入spring-boot-starter-jdbc或是更好用的spring-boot-starter-data-jpa.在使用Spring Boot构建应用的时候,各项功能模块的整合不再像传统Spring应用的开发方式那样,需要再pom.xml中做大量的依赖配置,而是通过Starter POMs定义的依赖包,使得功能模块整合变得非常轻巧,易于理解与使用。

Spring Boot的starter POMs采用spring-boot-starter-*的命名方式,*代表一个特别的应用功能模块,比如Web、test.

4.2 spring-boot-starter-test

通用测试模块,

包含JUnit、Hamcrest、Mockito.

5 命令行界面(CLI)

这是spring boot的可选择性,借此只需要写代码就能完成完整的应用程序,无需传统项目构建。

简单而言,在我们以往开发,在使用某些类时,我们会需要import进行导入,而CLI能够检测到我们使用了哪些类,知道向classpath中添加哪些起步依赖,添加起步依赖之后,就会进行相应的自动配置。

6 Actuator

深入了解运行中的spring boot应用程序。

在运行时检测应用程序内部情况。

包括:

1:Spring应用程序上下文里配置的Bean;

2:Spring-boot的自动配置做的决策;

3:应用程序取到的环境变量、系统属性、配置属性和命令行参数等;

4:应用程序里线程的当前状态;

5:应用程序最近处理过的HTTP请求的追踪情况;

6:各种和内存用量、垃圾回收、Web请求以及数据源用量相关的指标。

Actuator通过web端点和shell界面向外界提供信息。

7 其他

7.1 关于持久化

当我们在使用了Jpa持久化之后,实际上,我们只需要写一个接口继承JpaRespository,在JpaRespository中已经定义了一些方法,如果有需要添加自定义的方法,只需要在继承了JpaRespository中加自己自定义的方法,并再写相应的实现类即可。

为什么继承了JpaRespository接口却不用实现里面已经定义好了的方法参见:

对于JpaRespository已经定义好的方法,并不需要我们去写他们的实现方法,系统能够自动实现,这是因为其中spring-data-jpa中有一个SimpleJpaRepository类就是实现了JpaRespository接口,如果我们继承了JpaRespository的自定义接口没有写相应的实现类,那实现类就是SimpleJpaRepository;如果是写了相应的实现类,那我们的实现类就是我们自定义的实现类,而这又是SimpleJpaRepository的子类,所以在实现类里面也只需要写我们自定义方法的实现类即可,而不用去写那些JpaRespository之前定义好了的方法。

你可能感兴趣的:(Java进阶之路,java,spring,boot,spring)