Day14-07.SpringBoot原理-自动配置-方案

Day14-07.SpringBoot原理-自动配置-方案.

前面提到SpringBoot的原理是一道高频面试题,其实面试中问到SpringBoot的原理就是在问SpringBoot中自动配置的原理。上一小节提到了,我们解析自动配置的原理,就是来分析在SpringBoot项目当中,我们引入对应的依赖之后,是如何将依赖当中jar包当中所提供的bean以及配置类直接加载到当前项目的SpringIOC容器当中的,然后我们就可以直接使用了。

在我们的SpringBoot项目中,我们要使用第三方所提供的这个依赖,就需要将这个依赖的坐标导入进来。

看一下itheima-utils类中配置了哪些bean:

我们刚刚已经在我们的SpringBoot项目中将itheima-utils这个依赖引入进来了,那当前这个项目运行之后,Spring的IOC容器当汇总是否存在TokenParser和HeaderParser这几个bean呢?接下来做一个测试:

其他两个也没有找到报错了。也就是说我们导入进来的第三方依赖中所声明的bean和配置类没有生效!!!为什么?

这个原因我们之前在说IOC的时候讲到过,我们在类上加上Component注解来声明bean对象,这个注解就一定会生效么?其实并不是,这个注解还需要被Spring的组件扫描扫描到。而我们之前又提到,SpringBoot项目的当中,@SpringBootApplication这个注解它具有包扫描的作用,但是他的扫描范围是只扫描当前包及其子包。当前包是itheima,子包就是con.itheima下面的那些子包。试问他能否扫上第三方依赖当中所提供的com.example这个包?不可以!!

问题找到了!!怎么解决?

1、方案一:@ComponentScan组件扫描

既然SpringBoot只能扫描当前包及其子包,既然扫描不到其他包,我们就可以通过一个注解@ComponentScan来手动的指定我们要扫描的哪些包。比如这里我们就可以在SpringBoot的启动类上加上@ComponentScan注解来指定我们要扫描com.example这个包(第三方依赖提供的包),然后再指定我们要扫描itheima这个包(当前项目的包)。因为我们一旦显示的声明了@ComponentScan这个注解,原来的默认扫描的包就会被覆盖掉,所以这里我们还需要指定我们还要扫描com.itheima这个包。

@ComponentScan({"com.example", "com.itheima"})
@SpringBootApplication
public class SpringbootWebComfig2Application {...}

再运行测试类会发现三个bean对象都拿到了!!

此时可以回想一下,前面我们使用SpringBoot进行案例程序开发的时候,是不是也引入了很多第三方依赖?比如像pageHelper、mybatis等等。SpringBoot有没有让我们去配置组件扫描,然后让我们去指定扫描mybatis或者pageHelper插件这些第三方依赖所在的包?没有!!为什么没有采用这种方式呢?如果采用这种方式来完成自动配置,我们项目开发引入大量第三方的依赖,将来这个启动类上面进行组件扫描的包就非常多了。我们每使用一个第三方依赖,要想完成自动配置的操作,就需要扫描一个甚至多个包。所以这种方式会很繁琐,我们每使用一个第三方依赖,我们还得查看我们到底要扫描哪些包,而且这样进行包扫描,一个包下可能会有很多类,而其实bean对象以及配置类并没有几个,所以这种大范围的扫描性能也并不高。所以SpringBoot当中并没有采用这种方案。

2、方案二:@Import导入。使用@Import导入的类会被Spring加载到IOC容器中,导入形式主要有以下几种:
(1)导入 普通类

这个类上面不用加任何注解,import将这个类导入进来之后就可以将这个类交给Spring的IOC容器管理,成为IOC容器中的Bean对象。不管导入的这个普通类上面有没有加@Component注解,导入进来之后都会变成IOC容器中的Bean对象。

@Import({TokenParser.class})
@SpringBootApplication
public class SpringbootWebComfig2Application {...}
(2)导入 配置类

配置类导入进来之后,这个配置类当中所有的bean对象都会加载到IOC容器当中。

@Import({HeaderConfig.class})
@SpringBootApplication
public class SpringbootWebComfig2Application {...}
(3)导入 ImportSelector 接口实现类

这个接口中有一个接口方法,交selectImport。这个方法的返回值是Stirng类型的数组。这个String类型的数组中封装的是类名。其实封装的就是我们需要将哪些类交给IOC容器管理。可以直接将这些类的全类名封装在这个数组当中返回。

这种方式将来就可以把我要加载的类定义在一份文件当中,要加载哪些类最终我只需要来读取这个文件,将文件中的字符串读取出来封装到数组中,那这些类最终都会被加载到IOC容器当中。这里指定的是HeaderConfig这个类的全类名,就相当于我们要把这个配置类交给IOC容器管理。

@Import({MyImportSelector.class})
@SpringBootApplication
public class SpringbootWebComfig2Application {...}

测试发现都没问题。。。

(4)@EnableXxxx注解,封装@Import注解
@Import(TokenParser.class, HeaderConfig.class)
@SpringBootApplication
public class SpringbootWebConfig2Application{...}

我们通过Import这个注解,通过这三种形式都可以导入第三方依赖当中所提供的这些bean或者是配置类。但是想一下,如果基于这种方式来完成自动配置,将来引入一个第三方依赖我们还得清楚的知道我们到底要导入这个第三方依赖中哪些配置类和哪些bean对象,是比较繁琐的,用户体验还是不好。

但是反过来想,我们要使用这个第三方依赖,我到底要导入哪些bean和那些配置类,谁最清楚?是不是第三方依赖自身最清楚!!所以我们就不用在这里自己来指定要导入哪些bean对象和配置类了,我们让第三方依赖自己来指定。

怎么指定?常见的就是第三方依赖给我们提供一个注解,这个注解一般都是@EnableXxx开头,这个注解当中封装的就是@Import注解,然后在Import注解后面指定要导入哪些bean或者是哪些配置类。例如

这个@Import注解就是用来指定我到底要导入哪些配置类,这里指定的是importSelector这个接口的实现类MyImportSelector,这个类中就指定了我们要导入哪些配置类和Bean。第三方依赖提供这个注解过后,如果我们想开启第三方依赖的自动配置功能就很简单了,就不用我们再去记我们要导入哪些Bean和配置类了,上面加一个第三方提供的注解@EnableHeaderConfig,加上这个注解就相当于加上了@Import注解来导入了对应的Bean和对应的配置类。测试发现也没有问题!!

们要导入哪些Bean和配置类了,上面加一个第三方提供的注解@EnableHeaderConfig,加上这个注解就相当于加上了@Import注解来导入了对应的Bean和对应的配置类。测试发现也没有问题!!

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值