所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

Spring Boot自动配置源码解析|核心实现流程手把手解读

Spring Boot自动配置源码解析|核心实现流程手把手解读 一

文章目录CloseOpen

这篇文章就帮你把Spring Boot自动配置的“黑盒”拆开,从核心的@EnableAutoConfiguration注解讲起,手把手解析AutoConfigurationImportSelector的执行逻辑,拆解自动配置类的加载、条件判断(比如@ConditionalOnClass)、Bean注入的全流程。不是干巴巴的源码堆砌,而是跟着代码走——看Spring怎么扫描META-INF/spring.factories里的配置类,怎么根据你的项目依赖动态决定要不要装配某个Bean。

不管你是刚学Spring Boot的新手想搞懂“为什么能自动”,还是有经验的开发者想解决配置冲突、深挖原理,这篇源码解析都会帮你把自动配置的逻辑刻进脑子里。 咱们就从最基础的入口开始,一步步扒开Spring Boot自动配置的神秘面纱。

你有没有过这种情况?用Spring Boot搭项目时,引入个spring-boot-starter-web依赖,不用手动配置Tomcat,项目跑起来就有Web容器;加个spring-boot-starter-data-jpa,数据库连接池、EntityManagerFactory这些Bean自动就有了——明明没写几行配置,怎么就“自动”把活干了?我去年帮做电商的朋友排查过一个坑:他的项目同时引了Redis和MongoDB的Starter,结果Redis的配置死活不生效,查了半天才发现,是RedisAutoConfiguration上的@ConditionalOnMissingBean起了作用——他自己定义了一个RedisTemplate,把自动配置的覆盖了。那时候我才明白,搞懂自动配置的源码不是为了“装懂”,是真能解决实际开发里的麻烦。

从@EnableAutoConfiguration说起,自动配置的入口藏在这里

你肯定见过@SpringBootApplication这个注解吧?它其实是个“组合包”,里面包含了@EnableAutoConfiguration——这就是自动配置的“总开关”。我第一次点进@EnableAutoConfiguration的源码时,发现它用@Import导入了一个叫AutoConfigurationImportSelector的类,这才是自动配置的“核心大脑”。

AutoConfigurationImportSelector的作用很直白:帮Spring找到所有需要自动配置的类,然后把它们“搬进”Spring容器。它的selectImports方法是关键——这个方法会调用SpringFactoriesLoader.loadFactoryNames,去扫描所有Jar包下的META-INF/spring.factories文件。你打开这个文件看看,里面全是自动配置类的全路径名,比如RedisAutoConfigurationDataSourceAutoConfigurationWebMvcAutoConfiguration这些。我之前做过个“破坏实验”:把spring.factories里的RedisAutoConfiguration注释掉,重启项目后,Redis的自动配置真的没生效——这说明,Spring Boot是靠这个文件“精准定位”要自动配置的类的。

我再给你拆得更细点:SpringFactoriesLoader就像个“配置类探测器”,它会遍历项目里所有依赖的Jar包,把每个spring.factories里的EnableAutoConfiguration对应的类名收集起来,最后返回给AutoConfigurationImportSelector。你要是用IDEA的Debug模式跟着走一遍,会看到selectImports方法返回的字符串数组里,全是这些自动配置类的名字——这一步,就是自动配置的“找候选”阶段。

自动配置类怎么“聪明”判断要不要生效?看条件注解的魔法

找到自动配置类还不够,Spring Boot得知道“什么时候该用这个类”——比如DataSourceAutoConfiguration(数据源自动配置),总不能不管项目里有没有数据库驱动,都强行生成DataSource Bean吧?这时候,条件注解就登场了。

自动配置类上通常会挂一堆@Conditional开头的注解,比如@ConditionalOnClass(类路径存在某个类时生效)、@ConditionalOnMissingBean(容器里没有某个Bean时生效)、@ConditionalOnProperty(配置文件有某个属性时生效)。我给你列个常用的条件注解表,一看就懂:

注解名称 通俗解释 常见场景
@ConditionalOnClass 项目里有某个类,才生效 DataSourceAutoConfiguration依赖DataSource类
@ConditionalOnMissingBean 容器里没有某个Bean,才生效 RedisAutoConfiguration默认生成RedisTemplate,除非你自己写了
@ConditionalOnProperty 配置文件有某个属性,才生效 spring.mvc.static-path-pattern配置了才启用静态资源映射
@ConditionalOnWebApplication 是Web项目,才生效 WebMvcAutoConfiguration只在Web项目里生效

这些注解组合起来,就让自动配置类变得“聪明”了。比如我朋友的Redis配置冲突问题:他的项目里同时引了Jedis和Lettuce(都是Redis客户端),结果RedisAutoConfiguration默认选了Lettuce——因为@ConditionalOnClass先找到了Lettuce的RedisClient类。后来他想改成Jedis,只需要两步:排除Lettuce的依赖,或者在配置文件里写spring.redis.client-type=jedis——这就是条件注解的“灵活之处”。

再举个我自己的例子:我之前写了个自定义Starter,想实现“引入依赖就自动配置”。那时候我照着Spring Boot的自动配置类“抄作业”:给我的自动配置类加了@ConditionalOnClass({MyService.class})(只有项目里有MyService类才生效),加了@EnableConfigurationProperties(MyProperties.class)(绑定配置文件里的my.starter前缀属性),然后在META-INF/spring.factories里注册了我的自动配置类——结果真的能用!用户引入我的Starter,不用写配置就能用我的组件,跟Spring Boot自带的Starter一模一样。这让我彻底明白:原来自动配置的“魔法”,普通人也能复制。

自动配置的最后一步:把Bean“装”进Spring容器

找到符合条件的自动配置类后,接下来要做的就是装配Bean了。自动配置类里通常会用@Bean注解生成Bean,比如DataSourceAutoConfiguration里会生成DataSource Bean,RedisAutoConfiguration里会生成RedisTemplate Bean。但这些Bean的属性(比如数据库URL、Redis主机地址)是怎么来的?

答案在@EnableConfigurationProperties注解里。自动配置类上一般会加这个注解,比如DataSourceAutoConfiguration上有@EnableConfigurationProperties(DataSourceProperties.class)——它的作用是把DataSourceProperties类“导入”进来,然后绑定配置文件里的spring.datasource前缀属性。我之前做过个测试:在配置文件里写spring.datasource.url=jdbc:mysql://localhost:3306/test,然后在DataSourceAutoConfiguration里打个断点,发现DataSourceProperties里的url属性真的是这个值——这说明,自动配置类是靠“配置文件绑定”来给Bean设置属性的。

再给你讲个细节:自动配置类里的@Bean方法通常会依赖Properties类。比如RedisAutoConfiguration里的redisTemplate方法,会接收RedisConnectionFactory参数(这个参数也是自动配置生成的),然后用RedisTemplate的构造方法把它传进去。我之前 debug 过这个过程,看着RedisTemplate从“空对象”变成“能连接Redis的实例”,那种“把黑盒拆开”的感觉真的很爽——原来自动配置就是“把零散的零件按顺序拼起来”。

其实Spring Boot的自动配置没那么神秘, 起来就三步:

  • 找配置类:通过SpringFactoriesLoader扫描spring.factories,收集自动配置类;
  • 条件判断:用@Conditional注解筛选出符合当前项目环境的配置类;
  • 装配Bean:通过@Bean@EnableConfigurationProperties,生成Bean并绑定配置属性。
  • 你要是哪天遇到自动配置不生效的问题,不妨跟着这个思路查:先看spring.factories里有没有对应的配置类,再检查条件注解有没有满足,最后确认配置属性有没有绑对——亲测这些方法能解决80%的自动配置问题。

    比如我上周帮同事解决的“RabbitMQ自动配置不生效”的问题:他引了spring-boot-starter-amqp,但启动后没看到RabbitMQ的连接日志。我让他先查spring.factories,发现RabbitAutoConfiguration确实在里面;再看条件注解,@ConditionalOnClass({RabbitTemplate.class, Channel.class})——他的项目里刚好没有Channel类(因为RabbitMQ的客户端依赖漏引了);补完依赖后,自动配置果然生效了。

    怎么样?是不是突然觉得“自动配置”不再是“魔法”了?其实它就是Spring Boot帮你做了“找类、判断、装配”这些重复活,让你不用写一堆XML配置。你要是有兴趣,可以自己用IDEA的Debug模式跟着走一遍流程,肯定比光看文字更有感觉。

    如果你按这些方法试了,或者遇到了新的问题,欢迎回来跟我聊聊—— 把“黑盒”拆开的过程,本身就很有意思啊!


    @SpringBootApplication和@EnableAutoConfiguration有什么关系?

    @SpringBootApplication其实是个“组合包”注解,里面就包含了@EnableAutoConfiguration——这可是自动配置的“总开关”。你点进@SpringBootApplication的源码看看,就能找到@EnableAutoConfiguration的身影,它通过@Import导入了AutoConfigurationImportSelector类,这才是自动配置的核心逻辑起点,没有它 Spring Boot 根本不知道要去哪找自动配置的类。

    Spring Boot是怎么找到要自动配置的类的?

    Spring Boot靠的是SpringFactoriesLoader这个“配置类探测器”。AutoConfigurationImportSelector类会调用它的loadFactoryNames方法,去扫描项目里所有Jar包下的META-INF/spring.factories文件。这个文件里存着所有自动配置类的全路径名,比如RedisAutoConfiguration、DataSourceAutoConfiguration这些,Spring Boot把这些类收集起来,就是要自动配置的“候选名单”,后续再筛选符合条件的类生效。

    自动配置类怎么判断要不要在我的项目里生效?

    自动配置类靠一堆@Conditional开头的注解“做决策”。比如@ConditionalOnClass是说“类路径里得有某个类才生效”,像DataSourceAutoConfiguration得有DataSource类才会启动;@ConditionalOnMissingBean是“容器里没有某个Bean的时候才生效”,比如你自己定义了RedisTemplate,自动配置的就不会再生成了;还有@ConditionalOnProperty是“配置文件里有某个属性才生效”,比如spring.mvc.static-path-pattern配置了,静态资源映射的自动配置才会启用。这些注解组合起来,就让自动配置类能适配你的项目环境。

    自动配置类里的Bean,比如DataSource,属性是怎么来的?

    自动配置类的Bean属性是通过“配置文件绑定”来的。你看自动配置类上一般会加@EnableConfigurationProperties注解,比如DataSourceAutoConfiguration里就用它绑定了DataSourceProperties类。这个类会对应配置文件里的前缀属性,比如你写的spring.datasource.url、spring.datasource.username,都会自动装进DataSourceProperties的属性里,然后自动配置类再用这些属性去初始化DataSource Bean——相当于把配置文件里的内容“搬”到了Bean里。

    我自己定义的Bean,会影响Spring Boot的自动配置吗?

    大概率会。比如你自己写了个RedisTemplate的@Bean方法,那RedisAutoConfiguration里的RedisTemplate就不会生效了——因为它上面有@ConditionalOnMissingBean注解,意思是“容器里没有这个Bean的时候才生成”。我去年帮做电商的朋友排查过类似问题:他自己定义了RedisTemplate,结果自动配置的没生效,查了半天才发现是这个注解在起作用。所以自己定义Bean的时候,得注意会不会覆盖自动配置的内容。

    原文链接:https://www.mayiym.com/48014.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码