spring boot实战自动配置原理分析以及SpringBoot starter的理解
@Import({AutoConfigurationImportSelector.class})通过获取指定文件路径,导入路径下所有的bean到系统。
@Conditional 条件判断注解,
@ConditionalOnClass({RedisOperations.class}) 判断RedisOperations.clss 在系统中是否存在,不存在跳过
@ConditionalOnMissingBean({RedisConnectionFactory.class}) 表示的意思为:如果存在名称为RedisConnectionFactory的bean,则该部分代码直接忽略,这是Spring Boot人性化体现之一,开发者申明的bean会放在第一位,实在是太懂礼貌了~
@EnableConfigurationProperties({RedisProperties.class}) 引入配置类注解
springboot有哪些特别:
1. 快速搭建项目的脚手架。
2.依赖管理特性 更多的maven 的特性,但是springboot 给做到了统一做成了工具类。
2.1 提供了统一的版本控制,可以有效解决版本冲突。在父项目(spring-boot-starter-parent)通过 <dependencyManagement> 管理各种版本 和依赖
2.2提供了很多 spring-boot-start(每一个start就相当于一种场景) ,解决了对应场景所依赖的jia 包
3.自动配置特性。
通过 @SpringBootApplication 注解导入
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
通过 @EnableAutoConfiguration 注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
1. 分析 @AutoConfigurationPackage 总结 :它主要是获取容器的最外层包名利用@import 注解讲该包下的所有组件(bean)全部导入到容器中,完成我开发自定义bean的加载
1 2 3 4 5 6 7 8 9 10 | @Target ({ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @Documented @Inherited @Import ({AutoConfigurationPackages.Registrar. class }) //<strong>它主要是获取容器的最外层包名利用@import 注解讲该包下的所有组件(bean)全部导入到容器中</strong> public @interface AutoConfigurationPackage { String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; } |
2. 分析 @Import({AutoConfigurationImportSelector.class})
总结 :
1.他会先加载所有的自动配置类 xxxxAutoConfiguration
2. 每个配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿,xxxxProperties类和配置文件进行绑定。
3.生效的配置类,就会给容器中配置很多组件。有了组件 功能就有了。
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
spring 加载自动配置类依靠的是 SpringFactoriesLoader 类,该类会自动加载 ClassLoader 下所有 jar 包中的 META-INF/spring.factories 文件所配置的 Bean。
舉例子: RedisAutoConfiguration
配置类
首先来看RedisAutoConfiguration类上的注解:
@AutoConfiguration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
@ConditionalOnClass:表示存在对应的Class文件时才会去解析RedisAutoConfiguration,否则直接跳过不解析,这也是为什么在不导入Redis依赖Jar时工程能正常启动的原因
@EnableConfigurationProperties:表示对@ConfigurationProperties的内嵌支持,默认会将对应Class这是为bean,例如这里值为RedisProperties.class,其定义为:
@ConfigurationProperties(
prefix = "spring.redis"
)
public class RedisProperties {
private int database = 0;
private String url;
private String host = "localhost";
private String username;
private String password;
private int port = 6379;
private boolean ssl;
private Duration timeout;
private Duration connectTimeout;
private String clientName;
private ClientType clientType;
private Sentinel sentinel;
private Cluster cluster;
private final Jedis jedis = new Jedis();
private final Lettuce lettuce = new Lettuce();
RedisProperties提供对redis的配置信息,其前缀为spring.redis
,因此在上篇中配置的host、port等信息会配置到该类上,
随后@ EnableConfigurationProperties会将RedisProperties注册为一个bean。
@Import为导入配置,LettuceConnectionConfiguration
具体实现如下:
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RedisClient.class})
@ConditionalOnProperty(
name = {"spring.redis.client-type"},
havingValue = "lettuce",
matchIfMissing = true
)
class LettuceConnectionConfiguration extends RedisConnectionConfiguration {
LettuceConnectionConfiguration(RedisProperties properties, ObjectProvider<RedisStandaloneConfiguration> standaloneConfigurationProvider, ObjectProvider<RedisSentinelConfiguration> sentinelConfigurationProvider, ObjectProvider<RedisClusterConfiguration> clusterConfigurationProvider) {
super(properties, standaloneConfigurationProvider, sentinelConfigurationProvider, clusterConfigurationProvider);
}
@Bean(
destroyMethod = "shutdown"
)
@ConditionalOnMissingBean({ClientResources.class})
DefaultClientResources lettuceClientResources(ObjectProvider<ClientResourcesBuilderCustomizer> customizers) {
DefaultClientResources.Builder builder = DefaultClientResources.builder();
customizers.orderedStream().forEach((customizer) -> {
customizer.customize(builder);
});
return builder.build();
}
@Bean
@ConditionalOnMissingBean({RedisConnectionFactory.class})
LettuceConnectionFactory redisConnectionFactory(ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers, ClientResources clientResources) {
LettuceClientConfiguration clientConfig = this.getLettuceClientConfiguration(builderCustomizers, clientResources, this.getProperties().getLettuce().getPool());
return this.createLettuceConnectionFactory(clientConfig);
}
这里又涉及到一个重要的注解:@ConditionalOnMissingBean,其功能为如果存在指定name的bean,则该注解标注的bean不创建, @ConditionalOnMissingBean({RedisConnectionFactory.class})
表示的意思为:如果存在名称为RedisConnectionFactory的bean,则该部分代码直接忽略,这是Spring Boot人性化体现之一,开发者申明的bean会放在第一位,实在是太懂礼貌了~~
本篇中涉及到的注解比较多,其具体实现原理在以后有时间再具体分析。
再回到RabbitAutoConfiguration类的具体实现
首先来看:
@AutoConfiguration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}
@EnableAutoConfiguration 自动装配原理
1. 分析 @AutoConfigurationPackage 它主要是获取容器的最外层包名利用@import 注解讲该包下的所有组件(bean)全部导入到容器中,完成我开发自定义bean的加载
2.@Import({AutoConfigurationImportSelector.class})自动配置文件收集器
1.他会先通过 SpringFactoriesLoader 类的 FactoryClassNames 读取所有的自动配置类 xxxxAutoConfiguration 的全限定类名
2. 每个配置类按照条件进行生效(通过条件类@ConditionalOnClass({RedisOperations.class} 判断我们系统中是否有对应的字节码文件(我们引入了对应的jar包后字节码就有了),有的话就加载配置类,没有的就跳过 ) )。
3. 每个自动配置的类都有 (@EnableConfigurationProperties({RedisProperties.class})) 默认都会绑定配置文件指定的值。xxxxProperties里面拿,xxxxProperties类和配置文件进行绑定。系统中会给出默认的配置,我们也可以在配置文件中,覆盖系统给的默认配置。
4. 生效的配置类,就会被容器创建。有了组件功能就有了。
1 2 3 | 注意 1 . 自动注入 只注入 META-INF/spring.factories 中 key = org.springframework.boot.autoconfigure.EnableAutoConfiguration 2 . 我们自己写主动注入的时候必须要在 写 META-INF/spring.factories 中 key = org.springframework.boot.autoconfigure.EnableAutoConfiguration |
依赖管理特性:
版本控制 jia包依赖 管理:
springBoot 做了很多的start包, 通过提前在start中定义好版本,和管理好对应的jar包,子项目在使用的时候,就可以不用指定版本了和jar包依赖了。
SpringBoot starter的理解?
starter 可以理解为一种使用场景。这个场景需要用到哪些组件,当前start 会统一管理好,引入好。,Spring框架也给我们实现了将近50个好用的starter。
比如以前我们要用Mybatis框架,可能会引入各种的包才能使用。而starter就是做了一层封装,把相关要用到的jar都给包起来了,并且也写好了对应的版本。这我们使用的时候就不需要引入一堆jar包且管理版本类似的问题了。

现在很多开源的组件都会提供对应的springboot-starter包给我们去用,要做一个starter包并不难。参照Spring内置的实现就好了:1、在工程里引入 starter 打包相关的依赖。2、在我们工程内建spring.factories文件,编写我们配置类的全限类名。
项目实际使用:
1.公司在引入rocketMq的时候,在放在一个公司的通用的rpc common中,在这里用start的方式提前注入了 生产者 消费者 。这样我们在项目在使用的时候,只需要引入我们common 中自定义的start就行,项目启动后satrt通过自动注入的方式 注入mq相关的Bean
,我们在使用的时候,直接从ioc容器中获取生产者消费者bean就可以使用了。我们不需引入mq原始额包啊,导入mq的各种配置,以及mq相关对象的实例化了。
2. 和外部对接时。自定义了一个 加密认证的规则。做成了 start。这样使用起来方便
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具