SpringBoot09-自动配置原理
一、自动配置
在 传统 Spring 时代:
你要用数据库,得自己写一堆配置:
DataSource
、JdbcTemplate
、事务管理器……要用 MVC,也得自己配置视图解析器、消息转换器……
每个常用组件都要写大量
@Bean
或 XML,麻烦又容易出错。
Spring Boot 的目标:
自动帮你把常用组件配好,只要你在项目里引入对应的起步依赖(starter),就几乎可以开箱即用,起步依赖中的bean对象会自动注入到IOC容器中。
我们现在注入第三方bean的方式:
不是自动配置。
二、自动配置-源码分析
2-1、@SpringBootApplication
你平常写的启动类就是这样标注的:
@SpringBootApplication public class DemoApp { … }
它其实是一个组合注解,里面包含:
@SpringBootConfiguration
(相当于@Configuration
)@ComponentScan
(包扫描)@EnableAutoConfiguration
← 自动配置的关键
2-2、@EnableAutoConfiguration
打开自动配置开关。
内部用了
@Import(AutoConfigurationImportSelector.class)
这句的意思:交给
AutoConfigurationImportSelector
来决定要导入哪些配置类。
2-3、AutoConfigurationImportSelector
它实现了
ImportSelector
接口,里面有一个selectImports()
方法:String[] selectImports(…)
这个方法会去扫描
META-INF/spring.factories
或META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
这些文件在
spring-boot-autoconfigure
这个 jar 包里。里面列出了大量自动配置类,例如:
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration …
2-4、自动配置类
每个自动配置类本质上就是一个普通的 @Configuration
,例如:
@AutoConfiguration
@ConditionalOnClass(DispatcherServlet.class)
public class DispatcherServletAutoConfiguration {@Beanpublic DispatcherServlet dispatcherServlet() {return new DispatcherServlet();}
}
它们一般都加了各种 条件注解:
@ConditionalOnClass
:classpath 有这个类才加载@ConditionalOnMissingBean
:容器里没同类 Bean 才创建默认的@ConditionalOnProperty
:看配置文件开关
2-5、流程串起来
应用启动 → 执行
@SpringBootApplication
@EnableAutoConfiguration
生效 → 调用AutoConfigurationImportSelector.selectImports()
读取
spring.factories
/.imports
文件 → 找到所有自动配置类按条件注解筛选(有类、有依赖、没被用户覆盖、配置开关打开…)
注册满足条件的 Bean(如 DispatcherServlet、数据源、MVC 相关组件…)
2-6、通俗总结
Spring Boot 的自动配置就是:
启动时去 jar 包里的配置文件里找所有可能的配置类;
然后根据条件注解判断要不要加载;
满足条件的就自动注册 Bean(如 Web 容器、数据源、MVC 组件…)。
你不用手写样板配置,Boot 帮你搞定;如果不想用或要自定义,直接写自己的 Bean 或关掉开关即可。
三、自己封装一个 Spring Boot Starter 的基本套路
这张图演示的是把第三方 jar(common-pojo)里的类做成 Spring Boot 自动配置,然后在业务项目里“零配置”使用的完整流程。可以按步骤看:
① CommonConfig
—— 普通的配置类
@Configuration
public class CommonConfig {@ConditionalOnProperty(prefix = "country", name = {"name","system"})@Beanpublic Country country(@Value("${country.name}") String name,@Value("${country.system}") String system) {return new Country(name, system);}@Beanpublic Province province() {return new Province();}
}
作用:把
Country
、Province
这两个第三方类注册成 Spring Bean。@ConditionalOnProperty
:只有当配置文件里有country.name
和country.system
时才创建Country
。@Bean
:返回实例交给 IoC 容器管理。
如果只是单独项目使用,可以直接
@Import(CommonConfig.class)
;
但如果想封装成 starter,还需要后面的步骤。
② CommonAutoConfig
—— 自动配置类
@AutoConfiguration
@Import(CommonConfig.class)
public class CommonAutoConfig {}
用
@AutoConfiguration
(或老版本的@Configuration
+ 条件注解)声明这是一个自动配置类。@Import(CommonConfig.class)
:把真正声明 Bean 的CommonConfig
引入。
关键点:用户项目不用自己
@Import(CommonConfig.class)
,而是通过自动配置机制自动加载。
③/④ 注册到 spring.factories
或 .imports
在 common-pojo-1.0-SNAPSHOT.jar 的 resources/META-INF/spring/
下:
老版本(Spring Boot 2.x):
spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ cn.itcast.config.CommonAutoConfig
新版本(3.x 推荐):
org.springframework.boot.autoconfigure.AutoConfiguration.imports cn.itcast.config.CommonAutoConfig
作用:告诉 Spring Boot:“当有人引入我的 jar 时,把
CommonAutoConfig
作为自动配置类。”
业务项目(右边)
@SpringBootApplication
public class SpringbootRegistApplication { }
用户项目什么都不用写,只要:
引入了
common-pojo
这个依赖,并在
application.yml
配好country.name
、country.system
。
Spring Boot 启动时会:
扫描到 jar 包里的
AutoConfiguration.imports
。把
CommonAutoConfig
加入。CommonAutoConfig
又@Import
了CommonConfig
。满足条件注解后,自动创建
Country
、Province
Bean。
🔥 总结流程
写一个配置类
CommonConfig
,里面@Bean
注册需要的对象,配合条件注解。写一个自动配置入口
CommonAutoConfig
,@AutoConfiguration
+@Import(CommonConfig)
。在 jar 包的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
写入CommonAutoConfig
的全类名。用户只要引入这个 jar + 在配置文件里写参数,Spring Boot 会自动帮他装配好 Bean,
无需在业务代码手动@Import
或@Bean
。
这就是自己封装一个 Spring Boot Starter 的基本套路。
①②写配置类
③④注册到
spring.factories
/.imports
业务项目直接用
@SpringBootApplication
,即“开箱即用”。
四、小结
五、自定义starter
示例:
步骤一:快速创建两个mavne工程
步骤二:配置dmybatis-spring-boot-atutoconfigure工程的pom.xml文件,添加依赖。
仿照以上的依赖,进行添加。
步骤三:编写自动配置类
// 标识当前类是一个自动配置类
@AutoConfiguration
public class MybatisAutoConfig {// 注入SqlSessionFactoryBean@Beanpublic SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);return sqlSessionFactoryBean;}// 注入MapperScannerConfigure@Beanpublic MapperScannerConfigurer mapperScannerConfigurer(BeanFactory beanFactory){MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();// 扫描的包:启动类所在的包,及其子包List<String> packages = AutoConfigurationPackages.get(beanFactory);String p = packages.get(0);mapperScannerConfigurer.setBasePackage(p);// 扫描的注解mapperScannerConfigurer.setAnnotationClass(Mapper.class);return mapperScannerConfigurer;}}
步骤四:声明自动配置类的全类名
目的:让这个自定义的自动配置类被springboot读取到。
4-1、创建.import配置文件
配置文件名可以直接从添加的依赖中获取:
在dmybatis-spring-boot-atutoconfigure工程中创建相同路径的文件。
4-2、在配置文件中添加自动配置类的全类名
步骤五:dmybatis-spring-boot-starter模块,添加依赖管理
<!-- 引入自动配置模块对应的依赖 --><dependency><groupId>org.example</groupId><artifactId>dmybatis-spring-boot-autoconfigure</artifactId><version>1.0-SNAPSHOT</version></dependency><!-- 将自动配置模块中的所有依赖也引入 --><!-- 目的:方便以后排除,添加新的版本的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>3.1.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId><version>3.1.2</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.19</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>3.0.4</version></dependency>
步骤六:删除多余的pakages
步骤七:将项目中的mybatis-spring-boot-starter替换为自定义的starter
其余代码均不变!