SpringBoot自动配置
自动配置是SpringBoot的核心因素,SpringBoot在整合每一种第三方技术时,都离不开自动配置。但在了解自动配置之前,Spring容器如何进行对bean的加载以及加载控制也是一个非常重要的前提知识。
1. bean的加载方式
1.1 方式一:配置文件+<bean/>标签
最初级的bean的加载方式其实可以直击spring管控bean的核心思想,就是提供类名,然后spring就可以管理了。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--xml方式声明自己开发的bean-->
<bean id="cat" class="com.example.bean.Cat"/>
<bean class="com.example.bean.Dog"/>
<!--xml方式声明第三方开发的bean-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/>
<bean class="com.alibaba.druid.pool.DruidDataSource"/>
</beans>
1.2 方式二:配置文件扫描+注解定义bean
方式一需要将spring管控的bean全部写在xml文件中,这种方式并不是很友好,所以就有了第二种方式。哪一个类要受到spring管控加载成bean,就在这个类的上面加一个注解,还可以顺带起一个bean的名字(id)。这里可以使用的注解有@Component以及三个衍生注解@Service、@Controller、@Repository。
@Component("tom")
public class Cat {
}
但上面这种方式仅仅只是对bean的声明,spring并没有“感知”到这些bean。因此需要通过下列xml配置设置spring去检查哪些包,发现了对应注解,就将对应的类纳入spring管控范围。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--指定扫描加载bean的位置-->
<context:component-scan base-package="com.example.bean,com.example.config"/>
</beans>
1.3 方式三:注解方式声明配置类
方式三在方式二的基础上,使用Java类替换掉了在xml配置文件中写component-scan这种固定格式的配置。定义一个配置类并使用@ComponentScan替代原始xml配置中的包扫描这个动作,其实功能是基本相同的。
@ComponentScan({"com.example.bean","com.example.config"})
public class SpringConfig {
@Bean
public DogFactoryBean dog(){
return new DogFactoryBean();
}
}
总结:
-
本文的重点是了解SpringBoot自动配置的原理,因此只给出部分bean的加载方式以供参考学习;
-
bean的定义由前期xml配置逐步演化成注解配置,本质是一样的,都是通过反射机制加载类名后创建对象,对象就是spring管控的bean。
2. bean的加载控制
企业级开发中不可能在spring容器中进行bean的饱和式加载的,也即不管用不用,全部进行加载。所以在spring容器中,通过判定是否加载了某个类来控制某些bean的加载是一种常见操作。
下面的例子使用@ConditionalOnClass注解实现了当识别到加载了com.example.bean.Wolf类时加载对应的bean。
@Bean
@ConditionalOnClass(name = "com.example.bean.Wolf")
public Cat tom(){
return new Cat();
}
@ConditionalOnMissingClass注解控制当没有加载指定的类时才加载对应的bean。
@Bean
@ConditionalOnClass(name = "com.example.bean.Wolf")
@ConditionalOnMissingClass("com.example.bean.Mouse")
public Cat tom(){
return new Cat();
}
还可以判定是否加载了指定名称的bean。比如当前容器中已经提供了jdbcTemplate对应的bean,此时就不需要再加载一个全新的jdbcTemplate的bean了。通过@ConditionalOnBean注解实现。
@Bean
@ConditionalOnBean(name="jerry")
public Cat tom(){
return new Cat();
}
3. 自动配置工作流程
自动配置的意义就是加速开发效率,将开发者使用某种技术时需要使用的bean根据情况提前加载好,实现自动配置的效果。当然,开发者有可能需要提供一些必要的参数,比如要用mysql技术,导入了mysql的坐标,springboot就会将一系列的数据库操作相关的bean都提前声明好,但是需要开发者告诉springboot到底用哪一个数据库,即IP地址,端口等配置都需要通过配置文件告诉spirngboot,继而完成自动配置相关的工作。
3.1 核心原理
- springboot的开发人员先大量收集Spring开发者的编程习惯,整理开发过程每一个程序经常使用的技术列表,形成一个技术集A
- 收集常用技术(技术集A)的使用参数,得到开发过程中每一个技术的常用设置,形成每一个技术对应的设置集B
- springboot初始化Spring容器基础环境,读取用户的配置信息,加载用户自定义的bean和导入的其他坐标,形成初始化环境
- springboot将技术集A包含的所有技术在SpringBoot启动时默认全部加载,这时肯定加载的东西有一些是无效的,没有用的
- springboot会对技术集A中每一个技术约定出启动这个技术对应的条件,并设置成按条件加载,由于开发者导入了一些bean和其他坐标,也就是初始化环境,这个时候就可以根据这个初始化环境与springboot的技术集A进行比对了,哪个匹配上加载哪个
- 因为有些技术不做配置就无法工作,所以springboot开始对设置集B下手了。它统计出开发者使用某个技术时最常用的设置,然后把这些设置作为默认值直接设置好,这样可以减少开发者配置参数的工作量
- 但是默认配置不一定能解决问题,于是springboot开放修改设置集B的接口,可以由开发者根据实际需要决定是否覆盖默认配置
3.2 流程概述
自动配置就是自动把第三方的Bean加载到spring的IOC容器中去,不需要开发人员去手动的配置。自动配置其实从根本上来说就是一个bean的加载。
- 在springboot应用中,只需要在启动类上加入@SpringBootApplication注解,就可以去实现自动配置。@SpringBootApplication注解是一个复合注解,包括@EnableAutoConfiguration @Configuration @ComponentScan注解,三个注解的分别作用是:
- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
- @Configuration:允许在上下文中注册额外的 bean 或导入其他配置类
- @ComponentScan: 扫描被@Component 及其衍生注解(@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。
- springboot启动时先加载spring.factories文件中的org.springframework.boot.autoconfigure.EnableAutoConfiguration配置项,将其中配置的所有的类都加载成bean;
- 而@EnableAutoConfiguration注解是实现自动配置的核心注解,注解中通过AutoConfigurationImportSelector类来实现自动配置,这个类实现了ImportSelector接口,在该类中加载 META-INF/spring.factories 的配置信息,主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到IOC容器中去,从而完成自动配置。