笑死,面试官又问我SpringBoot自动配置原理

面试官:好久没见,甚是想念。今天来聊聊SpringBoot的自动配置吧?

候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的“特性”了。众所周知,SpringBoot有着“约定大于配置”的理念,这一理念一定程度上可以用“SpringBoot自动配置”来解释。

候选者:SpringBoot自动配置的原理理解起来挺简单的,我们在使用SpringBoot的时候,肯定会依赖于autoconfigure这么一个包

候选者:autoconfigure这个包里会有一个spring.factories文件,该文件定义了100+个入口的配置类。比如我们经常使用的redis、kafka等等这样常见的中间件都预置了配置类

候选者:当我们在启动SpringBoot项目的时候,内部就会加载这个spring.factories文件,进而去加载“有需要”的配置类。那我们在使用相关组件的时候,就会非常的方便(因为配置类已经初始化了一大部分配置信息)。

候选者:一般我们只要在application配置文件写上对应的配置,就能通过各种template类直接操作对应的组件啦。

面试官:那是所有的配置类都会加载吗?这个“有需要”的配置类你是怎么理解的?

候选者:不是所有的配置类都会加载的,假设我们没有引入redis-starter的包,那Redis的配置类就不会被加载。具体Spring在实现的时候就是使用 @ConditionalXXX进行判断的。比如Redis的配置类就会有@ConditionalOnClass({RedisOperations.class})的配置,说明当前环境下如果有RedisOperations.class这个字节码,才会去加载Redis的配置类

面试官:哦,这样啊,那了解了。那你知不知道Redis的配置类其实会有初始化RedisTemplate对象的操作,那假设我们没有引入redis-starter包,那他是怎么通过编译的?(当然了,其他的配置类也是有可能有一样的状况)

候选者:嗯,这个我看源码的时候我也发现了。其实就是在autoconfigure包里会定义到相关的依赖,但只是标记为optional并且只在编译环境有效。那这样是能通过编译的,只是不会将其依赖传入到我们的应用工程里

候选者:这块还是花了我很多时间的,我最后在GitHub 的SpringBoot源码里找到的。

面试官:嗯啊,有点东西的哟。既然都聊到这块了,要不顺便聊聊你对SpringBoot starter的理解?

候选者:嗯,starter这东西就是为了方便调用方去使用相关的组件的嘛,Spring框架也给我们实现了很多好用的starter。

候选者:比如以前我们要用Mybatis框架,可能会引入各种的包才能使用。而starter就是做了一层封装,把相关要用到的jar都给包起来了,并且也写好了对应的版本。这我们使用的时候就不需要引入一堆jar包且管理版本类似的问题了。

候选者:现在很多开源的组件都会提供对应的springboot-starter包给我们去用,要做一个starter包并不难。参照Spring内置的实现就好了:1、在工程里引入 starter 打包相关的依赖。2、在我们工程内建spring.factories文件,编写我们配置类的全限类名。

面试官:嗯,大致都了解了,可以的。最后聊下你是怎么看这块源码的?

候选者:源码具体大概就不记得了,思路倒是还有的。我先从启动类开始,会有个@SpringBootApplication,后面会定位到一个自动配置的注解@EnableAutoConfiguration,那最后就能看到注解内部会去META-INF/spring.factories加载配置类

候选者:这块源码并不难,这个过程也了解到了原来maven有option和scope这俩标签,但确实是SpringBoot比较重要的概念吧。

面试官:好嘞,今天到这就结束了吧。

题外:自动配置这个问题确实被问到过几次。说实在的,对于Spring类、注解的信息我真的记不住。感觉能答出这个流程思路,也就够用了(如果面试官确实是要细究某个类名,那这种公司不去也罢)

约定大于配置:SpringBoot给我们内置了很多配置类,这些配置类也初始化了很多配置(默认值)。当我们要使用的时候,只需要覆盖这些配置项就完事了。即便我们不写,大多数情况下都不需要由我们显示配置出来,但相关组件就能正常访问了。

<think>嗯,用户现在的是Spring Boot自动装配原理,这应该是在准备面试吧。我之前已经回答过SQL优化的题,现在用户可能是在继续准备技术面试,特别是Spring Boot相关的。我需要确保解释清楚自动装配的核心机制,因为这是Spring Boot的重要特性之一。 首先,我得回忆一下Spring Boot自动装配的关键点。记得自动装配主要依赖于@EnableAutoConfiguration和spring.factories文件,还有条件注解比如@ConditionalOnClass。用户可能需要一个结构清晰的回答,分步骤说明原理,可能还要对比Spring的传统配置,突出自动装配的优势。 接下来,用户可能想知道自动装配的具体流程,比如启动类上的@SpringBootApplication注解,它组合了@EnableAutoConfiguration。然后,Spring Boot会加载META-INF/spring.factories中的配置类,这些配置类使用条件注解来决定是否生效。需要举例子,比如DataSourceAutoConfiguration,这样更具体。 另外,用户可能对自动装配的底层机制不太清楚,比如如何扫描和加载配置类,条件注解的作用,以及如何排除不必要的自动配置。所以需要详细解释这些部分,可能还要提到@Import和AutoConfigurationImportSelector的作用,以及如何通过配置开启或关闭自动装配。 还要注意回答的结构,按照步骤分点,结合代码示例和注释,帮助用户理解。比如用代码块展示@SpringBootApplication的组成,或者spring.factories的内容。同时,要避免使用过于专业的术语,保持解释的易懂性。 最后,总结自动装配的意义,比如简化配置、约定优于配置、模块化设计,这样用户能理解为什么自动装配重要。可能还需要提到常见的扩展点,比如自定义starter,或者如何排除自动配置,这样用户在面试中遇到相关题也能应对。 检查一下有没有遗漏的关键点,比如条件注解的具体类型,或者自动装配的触发过程。确保覆盖到核心概念,并且用简洁明了的语言表达出来,这样用户能快速掌握重点,应对面试官的提。</think>以下是Spring Boot自动装配原理的逐步解析,按核心流程梳理: --- ### 一、核心机制总述 **核心目标**:自动加载符合条件的Bean到IOC容器,**无需手动编写XML或Java配置** **实现原理** = `@EnableAutoConfiguration` + `spring.factories` + **条件注解** --- ### 二、实现步骤拆解 #### 1. 入口注解:@SpringBootApplication ```java @SpringBootApplication // 复合注解 public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } ``` - 分解组成: ```java @SpringBootConfiguration // 标记为配置类 @EnableAutoConfiguration // 激活自动装配的核心注解 @ComponentScan(...) // 组件扫描 ``` --- #### 2. @EnableAutoConfiguration 的触发 - 通过`@Import`引入`AutoConfigurationImportSelector` ```java @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { ... } ``` - `AutoConfigurationImportSelector` 关键方法: ```java // 获取所有自动配置类 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); ``` --- #### 3. 加载自动配置类(spring.factories机制) - **扫描路径**:`META-INF/spring.factories` - **配置示例**(spring-boot-autoconfigure包中的文件): ```properties # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ ... ``` --- #### 4. 条件注解过滤 配置类通过**条件注解**动态判断是否生效: - `@ConditionalOnClass`:类路径存在指定类时生效 ```java @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) public class DataSourceAutoConfiguration { ... } ``` - 其他常用条件注解: - `@ConditionalOnMissingBean`:容器中没有指定Bean时生效 - `@ConditionalOnProperty`:配置参数满足条件时生效 - `@ConditionalOnWebApplication`:Web环境生效 --- ### 三、自动装配流程图示 ``` 启动类 ↓ @SpringBootApplication → @EnableAutoConfiguration ↓ AutoConfigurationImportSelector ↓ 加载META-INF/spring.factories中的配置类 ↓ 通过条件注解筛选有效配置类 ↓ 注册符合条件的Bean到IOC容器 ``` --- ### 四、关键验证方法 1. **查看生效的自动配置类** 在`application.properties`中添加: ```properties debug=true ``` 启动时会打印: ``` Positive matches: // 已启用的自动配置 Negative matches: // 未启用的自动配置 ``` --- ### 五、自动装配的扩展与定制 1. **排除指定自动配置类** ```java @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) ``` 2. **自定义Starter** - 创建`XXX-spring-boot-starter`模块 - 编写配置类并注册到`spring.factories` - 使用条件注解控制加载条件 --- ### 六、与传统Spring配置的对比 | 维度 | Spring传统模式 | Spring Boot自动装配 | |--------------------|------------------------------|----------------------------------| | 配置方式 | XML/Java显式声明Bean | 自动发现+条件装配 | | 依赖管理 | 手动管理依赖版本 | starter统一管理依赖 | | 环境适配 | 需手动切换Profile配置 | 自动根据classpath环境加载配置 | | 开发效率 | 配置繁琐 | 开箱即用 | --- ### 七、典型面试追点 1. **如何覆盖自动装配的默认配置?** - 自定义Bean(同名Bean优先级高于自动配置) 2. **自动装配与@ComponentScan的关系?** - `@ComponentScan`扫描当前包及子包的Bean - 自动装配加载第三方库的Bean(通过spring.factories) 3. **为什么引入starter依赖就能直接使用功能?** - starter中已包含`spring.factories`和条件配置类 --- ### 八、核心价值总结 1. **简化配置**:消除样板代码(如手动配置DataSource) 2. **约定优于配置**:通过默认配置快速启动项目 3. **模块化设计**:通过starter实现功能模块化装配
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值