Spring Boot框架
Spring Boot框架知识点:
1、Spring Boot框架的理解
Spring Boot提供了一种快速构建Spring项目的方式,基于约定优于配置的思想,可以让开发人员更多地关注逻辑代码,提高开发效率。(并不是在Spring框架的基础上进行功能增强,只是简化配置)
自动配置:在Spring Boot中定义了一系列的注解供使用,按照约定的方法进行配置,可以自动将对象的Bean放入Spring的IoC容器中。除了Spring框架中常用的@Configuration、@Bean、@Component、@Repository、@Service、@Controller可以在本项目中配置Bean外,还可以通过Spring Boot的起步依赖自动配置第三方包中的对象,此时只需要在配置文件中按照固定的书写方式指定第三方包中需要的参数即可。譬如,Spring Boot整合MyBatis框架只需要导入对应的起步依赖,然后在application.properties配置文件配置数据源、映射文件的位置(如果编写了MyBatis的核心配置文件,也需要指定该文件的位置),然后就可以在项目中自由注入操作dao层的代理对象了。
起步依赖:在Spring Boot中使用到的依赖是针对Spring Boot进行配置之后的,只需要在项目的配置文件中指定必须的参数,在启动Spring Boot项目之后,就可以生成相应的Bean对象。起步依赖是某项技术中需要使用的一系列依赖的组合,对版本进行了锁定,可以有效避免依赖冲突问题(Spring Boot项目继承自spring-boot-starter-parent,在该父工程中对需要使用的依赖进行版本锁定)。
辅助功能:Spring Boot提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。譬如嵌入式服务器,Spring Boot的spring-boot-starter-web依赖中提供了四种可供使用的服务器,可供切换使用,同时具有多种配置方式,项目中、项目外以及命令行等都可以进行配置,根据优先级的不同可以避免同时配置时的冲突。
2、Spring Boot的快速开发web项目
2.1 创建Spring Boot项目
使用IDEA创建Spring Boot项目,在Dependencies图形化界面中选中web,自动导入web依赖并创建引导类。
2.1 编写Controller和Service
编写Controller层和Service的方式与使用Spring MVC框架进行开发的时候一样,该使用什么注解还是用什么注解,但是不需要额外编写spring-mv.xml和application.xml配置文件。
2.2 编写Dao层
使用MyBatis框架充当持久层,引入mybatis-spring-boot-starter起步依赖,编写映射文件,可以使用全注解的方式编写mapper文件(创建一个mapper包,然后编写接口,接口使用@Mapper注解修饰),然后再定义方法,方法上使用@Select、@Insert、@Update、@Delete修饰(参数是sql语句,如果有需要还需要使用到@Result注解进行结果集的自动封装)。
2.3 配置的编写
在Resource目录下创建application.yml文件,配置数据源。
备注如果在MyBatis中使用了xml配置,还需要指定配置文件的位置
3、Spring Boot配置文件
3.1 配置文件的编写
Spring Boot中可以编写application.properties、application.yml、application.yaml三种配置文件,可以放置在项目根目录的下或根目录的config文件夹,项目resource目录下或该目录的config文件夹。不同位置的配置文件优先级不同,根目录config>根目录>resource的config>resource(不同位置的配置文件都会读取,当存在重复配置的时候优先级更高的生效,还有很多外部配置文件的加载,可以查看官网https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html)。
properties文件中书写键值对;
yml和yaml属于同一种数据格式,也是键值对,但是键之间可以存在层次结构,如下所示:
yaml或yml中的引用:
备注:yml和yaml中书写键值对的时候:1)value之前必须有空格,否则无法识别;2)使用空格表示层级关系,相同的缩进表示同一层级。
3.2 配置文件中信息的获取
在类中可以获取配置文件中的信息:
1)@Value
可以使用@Value(“${key}”)直接注入;
2)Environment对象
在Spring Boot启动之后,读取的配置文件会以Environment对象注入到IoC容器中,可以在类中注解注入该对象,然后通过getProperty方法获取value;
3)@ConfigurationProperties
可以使用@ConfigurationProperties 和@Componnet注解同时修饰一个类,项目在启动的时候会自动从配置文件中按属性注入该类的实例对象并放入IoC容器。
备注:@ConfigurationProperties 中有个prefix属性,可以限制key的前缀,满足前缀的属性才会注入。
3.2 profile配置
我们在开发Spring Boot应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址、服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。profile功能就是来进行动态配置切换的。
1) profile是用来完成不同环境下,配置动态切换功能的。
2) profile配置方式:
多profile文件方式:提供多个配置文件,每个代表一种环境。
application-dev.properties/yml 开发环境
application-test.properties/yml 测试环境
application-pro.properties/yml 生产环境
yml多文档方式:
在yml中使用 --- 分隔不同配置
3) profile激活方式
配置文件: 再配置文件中配置:spring.profiles.active=dev
虚拟机参数:在VM options 指定:-Dspring.profiles.active=dev
命令行参数:java –jar xxx.jar --spring.profiles.active=dev
4、Conditional注解
4.1 Condition注解的使用1
Spring Boot中提供了Conditional注解,可以实现满足一定条件之后才会加载某个Bean对象。该注解的参数是实现Condition接口的字节码对象的数组,Condition接口中有一个matches方法,如果参数中实现该接口的类中matches的返回值都是true时,才会加载这个Bean到IoC容器中。
示例代码如下:
定义一个空的Person类:
public class Person{}
定义一个实现Condition接口的实现类:
public class PersonCondition implements Condition{
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata){
//可以编写逻辑代码
return false;
}
}
定义一个配置类用于创建生成Person的Bean对象:
@Configuration
public class PersonConfiguraton{
@Bean
@Conditional(PersonCondition.class)
public Person person(){
return new Person();
}
}
在上述情况下,Condition接口实现类PersonCondition中的matches方法的返回值是false,则不会加载Person对象到IoC容器中,但是如果该方法的返回值是true则会加载。
4.1 Condition注解的使用2
分析Condition接口中的matches方法,可以发现方法中有两个形参:
1)conditionContext:上下文对象,可用于获取IoC容器、Environment对象和类加载器;
2)annotatedTypeMetadata:元注解对象,可用于获取被该@Conditional注解修饰方法或类的其他注解中的数据。
因此,可以通过自定义一个注解,然后设置属性并采用annotatedTypeMetadata对象获取该属性值,进而实现动态加载某个Bean的目的。
该自定义的注解可以与@Conditional注解一起配合使用,也可以使用@Conditional注解修饰这个自定义的注解,然后使用的时候直接使用这个自定义的注解(组合注解)即可。
示例如下:
需求:自定义一个注解用于判断是否引入相关的类,从而动态加载Bean
定义一个Condition接口实现类:
public class ConditionOnClass implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Map<String, Object> annotationAttributes = annotatedTypeMetadata.getAnnotationAttributes(ClassLoadCondition.class.getName());
String[] value = (String[]) annotationAttributes.get("value");
for (String v:value){
try {
Class.forName(v);
} catch (ClassNotFoundException e) {
return false;
}
}
return true;
}
}
自定义一个注解:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ConditionOnClass.class)
public @interface ClassLoadCondition {
String[] value();
}
定义一个类:
@ConfigurationProperties(prefix = "userbean")
@Component
@ClassLoadCondition("com.mysql.cj.jdbc.Driver")
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试:
@RestController
@RequestMapping("/test")
public class ControllerTest {
@Autowired
private User user;
@RequestMapping("/demo1")
public void user(){
System.out.println(user);
}
}
备注1:其实自定义的注解也可以不需要@Conditional注解修饰,此时User类上需要同时使用@Conditional(ConditionOnClass.class)和@ClassLoadCondition("com.mysql.cj.jdbc.Driver"),程序也能测试通过。
备注2:Spring Boot中提供了一些条件注解
ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
5、Spring Boot中的自动配置
5.1 导入Bean的方式
引导类上的注解@SpringBootApplication是实现自动配置的一个注解,其扫描范围是引导类所在包及其子包。除了默认的加载范围外,还可以使用一系列注解用于在启动Spring Boot项目的时候自动加载Bean对象。
@ComponentScan:指定需要扫描的包;
@Import:参数是Class数组,会加载指定的Class;
@Import注解参数的Class可以为指定的Bean、配置类、ImportSelector实现类和ImportBeanDefinitionRegistrar实现类。
1)ImportSelector实现类
该实现类可以复写selectImports方法,返回一个字符串数组,如果使用@Import注解并传入该实现类的字节码对象,将会自动加载该字符串数组指定的所有Bean,可用于批量配置Bean;
2)ImportBeanDefinitionRegistrar实现类
该实现类复写registerBeanDefinitions方法,在该方法中注册Bean对象,该Bean也会自动放入IoC容器中。
5.2 EnableAutoConfiguration注解
该注解是实现SpringBoot自动配置的核心,该注解内部使用了@Import(AutoConfigurationImportSelector.class)来加载配置好的类。
AutoConfigurationImportSelector是ImportSelector的实现类,该实现类方法中会读取META-INF/spring.factories文件(该文件中包含需要加载的配置类的全类名)。
并不是spring.factories文件中的所有配置类都会被加载,因为配置类中的Bean使用了@Conditioal注解修饰,只有满足一定条件才会加载。
6、Spring Boot中的监听
SpringBoot项目启动时会对几个监听器进行调用,我们可以实现这些监听器的接口,在项目启动的时候完成一些操作。
ApplicationRunner:实现run方法,在项目启动后执行(使用@Component注解放入IoC);
CommandLineRunner:实现run方法,在项目启动后执行(使用@Component注解放入IoC);
备注:可以在ApplicationRunner或CommandLineRunner实现类中预先加载项目所需要的数据。
ApplicationContextInitializer:只有一个initialize方法,会在容器开始准备之前执行。
SpringApplicationRunListener:这个接口的实现类用于检测项目启动的生命周期,SpringBoot中提供了EventPublishingRunListener实现类,这个监听器就是实现项目启动控制台打印的日志信息(该类的自动执行,需要写进项目的META-INF/spring.factories文件中)
7、SpringBoot的监控
SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况的监控,比如监控状态、Bean加载情况、配置属性、日志信息等。
1)导入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
3)访问http://localhost:8080/actuator即可(显示的是JSON字符串)
备注1:可以在配置文件中配置manager.endpoint.health.show-details=always显示完整的健康信息。可以配置manager.endpoint.web.exposure.include=*暴露所有监控的信息。
备注2:使用Spring Boot Admin可以实现图像化界面查看Spring Boot项目的监控。
8、SpringBoot项目的部署
可以打成jar包或war包,打成jar包可以直接执行,如果打成war包,需要使引导类继承SpringBootServletInitializer类。