SpringBoot开发项目,为什么这么简单?SpringBoot帮我们做了哪些事情?
了解SpringBoot的底层原理是有必要的。
面试重点
spring框架中各种jar包的依赖关系(还有各种jar包的版本适配)、还有各种配置非常繁琐
SpringBoot的两个优点:起步依赖、自动配置
springboot除了我们自己定义的bean对象和引入的第三方bean。还会自己配置一些配置的bean对象存入到IOC容器中,当我们需要使用时,直接使用@Autowired注入即可,从而简化了开发
加载bean对象的(即bean如何加载到spring的IOC容器中的)方法:
我们研究SpringBoot的自动配置原理,就是研究当我们在maven中引入依赖后,是如何将依赖jar包当中的所定义的配置类,以及这些bean如何加载到spring的IOC容器中。
方法1:通过@ComponentScan组件扫描的方式
通过@ComponentScan组件扫描的方式,添加第三方的bean到SpringIOC容器中
场景:当前在SpringBootWebConfig2Application的启动类中要使用itheima-utils包下的bean对象
(1)我们需要在springboot-web-config2中的pom依赖中引入itheima-utils依赖
(2)虽然itheima-utils包中的的自定义bean对象已经加了@Component注解,交由IOC容器管理,但是在在SpringBootWebConfig2Application的启动类中仍然访问是访问不到的。
因为SpringBoot的启动类默认只扫描当前包com.itheima,及其子包的bean对象
(3)此时,我们必须还要加上@ComponentScan注解来指定扫描包是"com.example"。但是会覆盖原有的扫描包。所以还要加上本地的扫描包
注意:为什么这里能扫描到"com.example"呢,因为加了上面的依赖,所以它知道去哪扫描,是扫描itheima-utils目录下的"com.example"路径
扫描包为多个,怎么书写?
@ComponentScan直接用value属性指定多个扫描包,即@ComponentScan({"xxx","xxx"})
或者
用@ComponentScan的basePackages属性指定多个扫描包
这样就可以扫描到第三方包的bean对象
开发SpringBoot项目,其实也引入了很多其他的第三方依赖,要想完成自动如果都以方法1书写,那@ComponentScan后面要加很多的扫描包
方法2:使用@Import导入
(1)导入itheima-utils中的普通类,这个类上不用加任何的注解,包括@Component
(2)导入itheima-utils中的配置类
(3)实现ImportSelector接口的实现类,重写里面的selectImports方法 ,返回值 表示 要交给IOC容器管理的类。
再在启动类上使用**@Import** 导入ImportSelector接口的实现类即可
这里我们要导入bean对象,还要知道要导入的类名,还是比较繁琐
要导入第三方的bean对象,只有第三方自己最清楚
方法3:以注解的形式导入
这个第三方定义的注解里面,使用了Import,导入了需要的bean,我们再使用这个bean对象的时候,只需要加上这个注解@EnableHeaderConfig即可,这个注解的@EnableHeaderConfig里面帮我们导入了需要的bean对象交给IOC容器管理
SpringBoot官方就是采用的第三种加注解的方式来导入bean对象
SpringBoot自动加载的原理
先要从启动类开始
(1)理解启动类上的注解@SpringBootApplication
@SpringBootApplication点进去
@SpringBootApplication作为一个注解,前4个都是作为注解的原注解
看第5个注解@SpringBootConfiguration,点进去
就只有定义了一个配置类的注解@Configuration,所以我们才可以在启动类上使用@Bean注解来导入第三方的类对象,来交给IOC容器管理
第7个注解,就是定义包扫描路径的,所以启动类只能扫描到当前包及其子包,将其中的bean对象交给IOC容器管理
自动配置的核心就是第6个注解@EnableAutoConfiguration
(1)@EnableAutoConfiguration 就是那个**@Import注解**,通过@Import注解来导入指定的bean或者配置类
(2)@Import注解,通过导入ImportSeletor(接口)实现类的方式,导入bean对象交给IOC容器管理
AutoConfigurationImportSeletor 就是ImportSeletor(接口)的实现类
AutoConfigurationImportSeletor里面重写selectImports方法
selectImports方法的返回值 表示 我需要将哪些类 交给IOC容器管理(返回值是字符数组,且类要指定全类名)
然后 selectImports方法 会去读取两份配置文件 ,在这两份配置文件中指定了大量需要自动配置的类
这两份配置文件在起步依赖中,好像 不同的起步依赖 包含的 这两份文件 都是一样的
这里面都是一个个配置类 的全类名,然后会加载每个配置类中用@Bean注解的bean对象交给IOC容器管理
配置类 中所有被**@Bean注解的bean对象** 都会直接交给IOC容器管理吗?并不是的。发现@Bean注解旁边还有**@ConditionalOnMissingBean注解**
@ConditionalOnMissingBean注解:这个注解的作用,就是按条件装配 ,当满足一定的条件之后,才会把这个bean注册到IOC容器中
@Conditional是条件装配的注解
可以加在类上,也可以加在方法上
(1)加在配置类上:对配置类中所有加了@Bean注解的都生效
(2)加在方法上:只对这一个加了@Bean注解的方法生效
第一个注解:
因为pom文件中已经引入了jwt依赖,这样环境中就有jwts对应的字节码文件,所以Headerparse这个bean会直接交给IOC容器管理
如果pom文件中去掉了jwt依赖,则IOC容器中不会有Headerparse这个bean
第二个注解:
使用场景:声明一个默认的bean对象,如果用户自己声明了这个bean对象,则这个bean不会生效,如果用户没有声明这个bean对象,还想使用这个bean,那么这个默认的bean对象就会生效
第三个注解:
配置文件中有这个属性和这个值,才会正常将该bean加入到IOC容器中
如果有这个属性,值不符合,也不会有这个bean。
第三个注解的使用场景:在SpringBoot中整合其他第三方的技术的时候,我们只有在对应的配置文件中,配置了对应的配置项,它才会声明对应的bean对象。
自定义Starter
有很多的第三方技术,它是没有起步依赖的,但是这个技术,在项目开发中又很通用,那么我们直接使用,使用起来就会比较繁琐
我们需要引入对应的依赖,在配置文件中进行配置,还需要基于官方SDK示例来改造对应的工具类,然后在项目中我们才可以使用。
例如,我们使用aliyunOss需要这么多的步骤,别的开发也需要这么多的步骤
第一个是springboot官方提供的起步依赖
下面两个是第三方提供的起步依赖 ,通常是命名方式是 功能在前, 一看就是mybatis或者pagehelper整合springboot所提供的起步依赖