SpringBoot核心原理:自动配置、starter、SPI机制

SpringBoot核心原理:自动配置、starter、SPI机制
SpringBoot核心原理自动配置、starter、SPI机制SpringBoot就像一个贴心管家你想要什么它提前帮你摆好不用你操心配置。但管家是怎么知道你想要什么的这篇就拆开它的脑袋看看。一、SpringBoot vs 传统Spring传统Spring项目有多折磨人一堆XML配置文件配个数据源能写半屏XML漏个分号项目就启动不了。SpringBoot的三个核心改变约定大于配置 sensible defaults你不配就用默认值内嵌Tomcat不需要单独部署war包java -jar直接跑零XML配置用注解和Java配置类替代XML一句话总结SpringBoot不是新框架它是Spring的全家桶套餐自动安装服务。二、起步依赖(starter)原理2.1 starter是什么starter是SpringBoot提供的一组依赖打包方案。比如你引入spring-boot-starter-webdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency一个依赖进来背后实际上带了一大堆东西包含的依赖作用spring-webSpring MVC核心spring-webmvcMVC框架tomcat-embed-core内嵌Tomcatjackson-databindJSON序列化spring-boot-starter-validation参数校验2.2 依赖传递机制Maven的依赖传递transitive dependency是starter能工作的底层机制。A依赖BB依赖CA自动获得C。所以你只写一行dependencyMaven帮你把整棵依赖树拉进来。这就是为什么SpringBoot项目的pom.xml看起来特别干净——复杂度被starter封装掉了。三、自动配置核心原理这是SpringBoot的灵魂所在。3.1 SpringBootApplication注解拆解启动类上的SpringBootApplication是个复合注解拆开看SpringBootConfiguration// 本质是Configuration标记配置类EnableAutoConfiguration// 自动配置的开关ComponentScan// 组件扫描扫描当前包及子包publicclassMyApplication{...}核心是EnableAutoConfiguration。3.2 从注解到AutoConfiguration.importsEnableAutoConfiguration通过Import(AutoConfigurationImportSelector.class)引入了一个选择器这个选择器做的事情是读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件把里面列出的所有自动配置类加载进来SpringBoot 3.x之前用的是META-INF/spring.factories3.x之后改成了AutoConfiguration.imports文件目的更清晰——把自动配置类和普通SPI配置分开。文件内容长这样org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration ... (几百个)3.3 条件装配注解光加载配置类还不够如果项目里没引Redis依赖RedisAutoConfiguration加载了也白搭。所以每个配置类上都有一堆条件注解注解条件ConditionalOnClassclasspath存在指定类时才生效ConditionalOnBean容器中存在指定Bean时才生效ConditionalOnProperty配置文件中存在指定属性时才生效ConditionalOnMissingBean容器中不存在指定Bean时才生效让你能覆盖默认配置ConditionalOnWebApplication是Web应用时才生效举例AutoConfigurationConditionalOnClass(RedisOperations.class)EnableConfigurationProperties(RedisProperties.class)publicclassRedisAutoConfiguration{// 只有classpath有Redis相关类这个配置类才会生效}3.4 自动配置执行流程启动main方法 → 创建SpringApplication → refreshContext() 刷新容器 → invokeBeanFactoryPostProcessors() → AutoConfigurationImportSelector执行 → 读取AutoConfiguration.imports → 加载所有自动配置类 → 逐个进行Conditional条件判断 → 条件满足 → 注册Bean到容器 → 条件不满足 → 跳过四、SPI机制简介4.1 什么是SPISPIService Provider Interface是一种服务发现机制。核心思想定义接口在API包中实现在各个SPI包中运行时动态发现并加载实现。4.2 Java SPI vs SpringBoot SPI对比项Java SPISpringBoot SPI配置文件位置META-INF/services/META-INF/spring/配置文件名接口全限定名AutoConfiguration.imports加载机制ServiceLoaderAutoConfigurationImportSelector是否支持条件过滤否全部加载是通过ConditionalJava SPI的缺点是一刀切全加载SpringBoot在此基础上加了条件判断只加载需要的这就是进步。五、实战自定义一个starter光说不练假把式我们来手写一个简单的starter。5.1 项目结构hello-spring-boot-starter/ # starter模块空jar只做依赖声明 └── pom.xml hello-spring-boot-autoconfigure/ # 自动配置模块 ├── src/main/java/com/example/hello/ │ ├── HelloProperties.java # 配置属性绑定类 │ ├── HelloService.java # 核心服务类 │ └── HelloAutoConfiguration.java # 自动配置类 └── src/main/resources/ └── META-INF/spring/ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports5.2 核心代码配置属性类ConfigurationProperties(prefixhello)publicclassHelloProperties{privateStringnameWorld;privateinttimes1;// getter/setter省略}服务类publicclassHelloService{privateHelloPropertiesproperties;publicStringsayHello(){StringBuildersbnewStringBuilder();for(inti0;iproperties.getTimes();i){sb.append(Hello, ).append(properties.getName()).append(!\n);}returnsb.toString();}// setter省略}自动配置类AutoConfigurationConditionalOnProperty(prefixhello,nameenabled,havingValuetrue,matchIfMissingtrue)EnableConfigurationProperties(HelloProperties.class)publicclassHelloAutoConfiguration{BeanConditionalOnMissingBeanpublicHelloServicehelloService(HelloPropertiesproperties){HelloServiceservicenewHelloService();service.setProperties(properties);returnservice;}}AutoConfiguration.imports文件内容com.example.hello.HelloAutoConfiguration5.3 使用方式别的项目引入这个starter后直接注入就能用RestControllerpublicclassTestController{AutowiredprivateHelloServicehelloService;GetMapping(/hello)publicStringhello(){returnhelloService.sayHello();}}在application.yml中配置参数hello:name:黑漂技术佬times:3启动项目访问/hello就能看到效果了。这就是SpringBoot自动配置的完整闭环starter声明依赖 → AutoConfiguration.imports注册配置类 → Conditional条件判断 → EnableConfigurationProperties绑定参数 → 注册Bean → 业务代码直接注入使用。