SpringBoot学习总结

SpringBoot学习总结


概要

  1. 记录下SpringBoot使用哪些注解简化了Spring的一些繁琐的配置
  2. 使用这些注解展示一下自己写好的一个自定义的start
  3. 查看一些SpringBoot的源码,来看看SpringBoot最初是如何启动,如何完成一些自动配置并将一些实例加入到IOC容器中的。
  4. 查看一些SpringBoot自己写的starter,也就是那些被成为起步依赖的东西。

一、SpringBoot向IOC容器注入实例

一开始学习Spring的时候,就感觉一大堆xml文件十分麻烦,每次都要复制粘贴很多重复的dtd引用之类的信息,另外,xml文件可读性不强,而SpringBoot,它首先就帮我们解决了这个问题。

  1. 用一个示例展示SpringBoot向ioc容器中注入实例的过程(该例子在下文会有详细介绍,此处只是粗略地介绍下几个注解)

在这里插入图片描述

上图中加上了@Configuration注解的类相当于Spring中的一个xml文件,它向Spring容器注入了一个PoetrySercvice和一个DataSource的实体类,其中的@Bean注解就相当于Spring中xml文件的bean标签。
那么,如何向实体类中注入属性值呢?

@Data
@ConfigurationProperties(prefix = "jdbc")
public class JdbcProperties {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
}

首先要获取属性值,上面代码中这个带@ConfigurationProperties注解的类是一个JavaBean,会向SpringBoot默认的配置文件(文件名固定为application,可以是yml、properties类型的文件。)中读取以jdbc为前缀的信息。

下图是application.yml文件中的部分内容。显然,该配置文件要生效的前提,是前缀后的key要与JavaBean中的属性名一致。

jdbc:
  driverClassName: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://localhost:3306/poetry?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
  username: root
  password: yudong

在这里插入图片描述

如上图所示,通过@EnableConfigurationProperties这个注解,就可以使用上面提到的JavaBean(JdbcProperties类)对DataSource实体类进行属性值的注入了(由此可知,@ConfigurationProperties注解是会将JavaBean实体类注入到ioc容器中的)。下面是注入过程的一些代码

另外需要注意的是@EnableConfigurationProperties注解和@ConfigurationProperties注解是配套使用的,两者如果不对应,在ide中是会报错的。

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(jdbcProperties.getDriverClassName());
        dataSource.setUrl(jdbcProperties.getUrl());
        dataSource.setUsername(jdbcProperties.getUsername());
        dataSource.setPassword(jdbcProperties.getPassword());
        return dataSource;
    }
  1. 注入过程小结
  • 首先有一个SpringBoot的默认配置文件,里面写了一些需要注入的内容
  • 然后通过@ConfigurationProperties注解的JavaBean读取配置文件中的内容
  • 接着@EnableConfigurationProperties注解的类使用上一步中的JavaBean通过@Bean注解的方法向Spring的ioc容器中注入实体类。
  • 不过如果要注入的属性值较少且有对应的构造方法,也可以像下面这样直接省去第二步骤,用更简洁的方式完成属性的注入
@Bean
// 声明要注入的属性前缀,Spring Boot会自动把相关属性通过set方法注入到DataSource中
@ConfigurationProperties(prefix = "jdbc")
public DataSource dataSource() {
return new DruidDataSource();
}

下面的内容是这个过程使用过的注解的一个总结

  • @Configuration:声明一个配置类,代替了Spring中的xml文件
  • @Bean:向Spring容器中注入实体,代替了Spring中的bean标签
  • @ConfigurationProperties(prefix=“xxx”):从SpringBoot中默认的配置文件中读取配置信息,该注解比@Vule更强大,不仅可以注入基本类型的数据,也能注入类成员变量
  • @EnableConfigurationProperties({xxx.class,xxx.class(可有多个配置类)}): 和@ConfigurationProperties注解一起使用,使被@ConfigurationProperties注解的类可以生效并被加入到IOC容器中。且该注解一般与@Configuration一起使用。

补充:SpringBoot的默认配置文件也可以有多个,配置方式此处不再赘述。

二、自定义的starter

在这一部分内容中,将通过一个自定义的starter,来展示如何利用SpringBoot写一个可被重复利用的模块,以图减少代码的冗余。通过自己写这样一个模块,也可以加深我们对SpringBoot各个注解的理解。
  1. 项目内容概述:这个starter,简单地实现了从数据库取出数据并装入一个Bean中然后加入IOC容器。

  2. 具体来说是数据库有两张表,一张存有唐诗数据,一张存有宋词数据,starter根据配置信息从数据库取出所需信息,装入对应的Song类或Tang类实例对象,然后将实例对象加入IOC容器供其他模块使用。

  3. 数据库名为:poetry,其中有两张表,表名分别为:song,tang

  4. 表结构(两个表结构是一样的)如下图所示:
    在这里插入图片描述

  5. 使用mybatis-plus从数据库取数据,过程十分简单(具体可参考一些mybatis-plus使用的文章博客等资料),同理可创建唐诗的相关类。
    先创建接受数据库信息的实体类

@Data
public class Song {
    //id
    private Long id;
    //作者名
    private String author;
    //题目
    private String title;
    //内容
    private String content;
}
  1. 创建对应的接口
public interface SongMapper extends BaseMapper<Song> {
}
  1. 创建Service,这个Service进行了一些简单的逻辑处理,其中只有一个得到内容的方法,它根据传来的朝代参数,确定从哪个表中取数据,然后根据其他参数,确定要取出的唐诗或宋词的内容。代码如下所示:
@AllArgsConstructor
public class PoetryService {

    private String author;
    private String title;
    private String dynasty;

    @Autowired
    private TangMapper tangMapper;

    @Autowired
    private SongMapper songMapper;

    public String getContent(){

        if (dynasty.equals("Tang") ){

            QueryWrapper<Tang> tangQueryWrapper= new QueryWrapper();
            tangQueryWrapper.eq("author",author);
            tangQueryWrapper.eq("title",title);
            Tang tang = tangMapper.selectOne(tangQueryWrapper);
            return tang.getContent();

        }
        else if (dynasty.equals("Song"))
            {
                QueryWrapper<Song> songQueryWrapper = new QueryWrapper<Song>();
                songQueryWrapper.eq("author",author);
                songQueryWrapper.eq("title",title);
                Song song = songMapper.selectOne(songQueryWrapper);
                return song.getContent();
            }
         else return "朝代有误";

    }

}

  1. 上面的步骤中没有用任何注解,只是实现了从数据库中取得数据的一些必要类并写了一个功能,而下面的内容将会实现将数据源和Service实体类注入IOC容器中。
  2. 只写上面的内容,是没办法从数据库拿数据的,因为没有数据源,压根也没有跟数据库建立连接,所以需要先向IOC容器里注入一个数据源。注入数据库的内容在上面已经展示过了,这里不再重复。
  3. 为了完整地展示项目,下面记录一下 向IOC容器注入Service的过程(与注入数据源过程类似,可跳过11-13的内容)
  4. 首先是创建一个从配置文件接受配置的JavaBean
@Data
@ConfigurationProperties(prefix = "myconfig")
public class MyProperties {
    private String author;
    private String title;
    private String dynasty;
}
  1. 对应的配置信息可以如下图一样设置,然后Service就能拿出水调歌头的内容
    在这里插入图片描述
  2. 然后在配置类的注解中加入该类即可。
    在这里插入图片描述

可能有人会问,这个模块中并没有启动类,那如何利用Bean注解向IOC容器加入实例对象呢?
答:这个模块在安装推送到远程仓库后,是会作为依赖被其他springboot项目引用的,当其他项目启动时,这个模块里的内容才有可能生效。显然,该模块向Bean注入的属性值,也是从其他项目的application文件中读取的。

那么其他项目只要引用该模块就能注入实例吗,这是有条件的。带@ConditionalOnxx的注解表明只有满足一定条件时该配置才能启动,“@ConditionalOnxx”中的“xx”可以是“Class”,“Properties”等,表示当某些类存在或者符合某些配置时,带有该注解的配置类可以启动。
下图中的例子,表示在配置文件中,当前缀mystarter中属性名为isopen的属性值为true时该配置类生效,而matchIfMissing表示如果配置类中没有这样的前缀和这样的属性值时,该配置类是默认生效的。

在这里插入图片描述

  1. 只有上面提及的内容,还无法让依赖starter的项目在启动时就能将需要的JavaBean注入到IOC容器中。毕竟如果只是现在这样写代码,那如果想找到这么一个配置类,就得扫描所有依赖里的所有包中的所有类,这显然是低效。所以,要将需要被使用的配置类放在一个容易被找到的地方,而这个地方,就是下图的spring.factories
    在这里插入图片描述
  2. 打开这个文件,在里面写入配置类的全限定名,就能在SpringBoot项目启动时扫描到这个类并且执行需要的IOC注入工作。springfactories文件里打开后如下图所示
    在这里插入图片描述

补充:该spring.factories文件需要在该starter模块中,所以SpringBoot在扫描的时候才能以该项目的classpath以及限定名找到这个具体的MyConfig类所在的位置。

  1. 具体的SpringBoot扫描过程将在下面的内容中有个概括性的讲解。
  2. 下图是在引用了该starter模块的一个测试控制类,此时就可以直接从IOC容器中取出poetryService实例,并享受它提供的服务。
    在这里插入图片描述
  3. 最后是测试类运行的结果
    在这里插入图片描述

三、自动配置原理

SpringBoot真正强大的地方并不是上面提到的化Spring之繁为注解之简,而是它集合了各种Spring平台的应用和第三方组件的内容。引入一些起步依赖后,通过使用注解和yml文件,SpringBoot允许我们使用简洁优雅的设置就能让程序run起来,远离了版本依赖错误和让人眼花缭乱的复杂配置问题。
这一节我将尽量跟踪一些源码,来探究一下SpringBoot项目在启动时是如何注入其他组件内容的,即自动配置的原理

首先来看看SpringBoot项目在运行的时候的入口:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

关于SpringBoot的注解

  1. 进入@SpringBootApplication注解,能发现其中需要关注的注解有以下几个:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM,
				classes = AutoConfigurationExcludeFilter.class) })
  1. 进入@SpringBootConfiguration注解,如下图,可以看到它继承了Configuration的注解,说明带有@SpringBootConfiguartion注解的类,相当于一个xml文件,可以在里面使用@bean注解注入实例
    在这里插入图片描述

  2. 进入@EnableAutoConfiguration注解,可以发现,这个注解,就是在刚才自定义starter中,在spring.factories文件中写的一个类(如下图所示)。所以这个注解的作用,就是使得(以下面的config.MyConfig为例)config.MyConfig这个配置类能够在SpringBoot项目启动时自动进行配置。

在这里插入图片描述在这里插入图片描述
3. 进入@ComponentScan注解,可以看到这个注解是可以不断扫描组件的,扫描的位置,是位于@SpringBootApplication注解类所在位置及其以下包里的内容。
在这里插入图片描述

总结一下,这三个注解,@SpringBootConfiguration表明Application类是唯一的SpringBoot配置类,@EnableAutoConfiguration注解使Application类可以加入其他配置类,@ComponentScan注解使Application类可以扫描配置该SpringBoot里的组件。

SpringBoot的一些方法

SpringBoot项目启动时,先初始化了一个SpringApplication类,进入其构造函数可以看到其初始化时发生的一些关键内容如下:

  1. 从方法名字可以看出,初始化时使用了很多SpringFactoriesInstances,这些工厂是可以用来向IOC中注入实例,下面我们进入getSpringFactoriesInstances方法查看SpringBoot如何得到这些工厂类。
    在这里插入图片描述
    在这里插入图片描述
  2. 通过一个上下文初始化类(ApplicationContextInitializer)的class作为参数,getSpringFactoriesInstances可以找到一个存有类限定名的Set集合,使用传进来的ApplicationContextInitializer.class进入该loadFactoryNames方法:
    在这里插入图片描述
  3. 查看这个FACTORIES_RESOURCE_LOCATION静态final属性有:
    在这里插入图片描述
    可以发现,其地址是: META-INF/spring.factories ,我们知道,ClassLoader默认是从classpath下读取文件,因此,SpringBoot会在初始化的时候,加载所有classpath:META-INF/spring.factories文件,包括jar包当中的。
  4. @EnableAutoConfiguration注解可以自动启动配置类,其中的可自动配置类被写在了spring.factories文件中。在Application启动时,会从spring.factories文件中得到可自动配置的类并加入需要的bean实例。
  5. SpringBoot加入了一些常用的可能会被用到的组件,并将他们配置类写在了一个包里,配置类的限定名写在该包的spring.factories中:
    在这里插入图片描述
    在这里插入图片描述
    从spring.factories可以看出,其中还有其他自动注入的内容。

四、起步依赖

  1. 起步依赖这个部分紧接着上一节的内容。在上一节的spring.factories文件中,可以看到里面有许多配置类,然而这些配置类并不是都会生效的,因为如前面说过的,配置类想要生效,需要有一定的条件,当需要需要的的类没有被注入时,配置类是无法生效的。
    下图举了一个例子,由于我没有注入该配置类生效时需要的类,所以该配置类也不会生效。
    在这里插入图片描述
  2. 想要对应的配置类可以生效,需要注入对应的一些starter。
    在这里插入图片描述
    在这里插入图片描述
  3. 进入在pom文件里加入的启动依赖,可以发现每个starter加入的依赖,都有具体版本号,这里就是springboot为程序员进行的版本控制。
    在这里插入图片描述
  4. 找到RestTemplate类,可以发现它所在的包,就是在starter中被导入的子依赖。
    在这里插入图片描述
    在这里插入图片描述

总结

SpringBoot项目其实与Spring项目没什么区别,两者能做的事情是一样的。但是SpringBoot帮助我们提前做了很多配置,使得我们只需要在pom文件中加入一些起步依赖starter的gav坐标就能完成在Spring中需要加入一大堆xml文件的配置工作。而SpringBoot新加入的一些注解,也方便了我们自己加入一些配置,让我们可以更优雅简洁地完成一些在Spring中存在冗余内容的工作。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值