SpringBoot自动配置的魔法
Spring自动配置
从@SpringBootApplication注解说起
SpringBoot会根据类路径下的类自动配置,省去了编写繁琐的xml配置文件。原本基于xml配置bean的方式编程基于Java代码,并且可以条件化配置,根据不同的场景配置也随之不同。是不是很智能
为了清楚SpringBoot自动配置的原理,我们从最简单的SpringBoot的启动类说起,看一个简单的启动实例
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
SpringBoot应用的启动很简单,就是一个main方法,然后执行SpringApplication的run方法。先不关心run方法是怎么执行的。我们先看SpringBoot应用的核心注解@SpringBootApplication
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
.....
}
查看该注解的源代码可知,这是一个组合注解。
分别查看每个注解的含义
@SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
可知该注解就是@Configuration注解,该注解什么这个一个配置类,在SpringBoot中很常见。
@CompontScan注解指定哪些包扫描或者不扫描。
使SpringBoot应用拥有自动配置魔法的注解是@EnableAutoConfiguraion。该注解可以让SpringBoot根据类路径中的依赖为当前项目进行自动配置 ,所以SpringBoot可以自动配置主要是因为SpringBoot应用上的@EnableAutoConfiguraion注解来实现的,所以在启动类上加入该注解,就会开启自动配置。
那么,这个注解是如何实现自动化配置的呢。接下来我们要一探究竟。
自动配置背后的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
.....
}
该注解也是一个组合注解,这里有一个@Import(AutoConfigurationImportSelector.class),那么@Import注解的作用是什么呢,查看@Import的源码注释,写着Indicates one or more {@link Configuration @Configuration} classes to import.Provides functionality equivalent to the {@code <import/>} element in Spring XML.,注释表明这个注解指明了要导入的配置类,在功能上和Spring XML配置中的<import>相同
那这里@Import导入的一个AutoConfigurationImportSelector又什么作用呢?根据下面注释中的内容可以知道,@Import允许导入ImportSelector,ImportBeanDefinitionRegistrar的实现类,还有普通的类(在版本4.2后)
Allows for importing {@code @Configuration} classes, {@link ImportSelector} and {@link ImportBeanDefinitionRegistrar} implementations, as well as regular component classes (as of 4.2; analogous to {@link AnnotationConfigApplicationContext#register}).
到了这里,说一个与@Import注解相关的东西,Spring框架本身提供了几个以Enable打头的注解,根据名字可知这是开启某个功能,比如
@EnableScheduling、@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和这些注解其实是相同的的。
@EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。@EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。
@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器。
接下来关注EnableAutoConfigurationImportSelector 这个作用是什么。主要就是使用Spring 4 提供的的SpringFactoriesLoader工具类。通过SpringFactoriesLoader.loadFactoryNames()读取了ClassPath下面的META-INF/spring.factories文件
EnableAutoConfigurationImportSelector通过读取spring.factories中的key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的值。如spring-boot-autoconfigure-1.5.1.RELEASE.jar中的spring.factories文件包含以下内容:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
如果我们新定义了一个
starter的话,也要在该starter的jar包中提供META-INFO/spring.factories文件,并且为其配置org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置类
从EnableAutoConfiguration寻找一个配置类CacheAutoConfiguration
@Configuration
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
@Import(CacheConfigurationImportSelector.class)
public class CacheAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public CacheManagerCustomizers cacheManagerCustomizers(
ObjectProvider<List<CacheManagerCustomizer<?>>> customizers) {
return new CacheManagerCustomizers(customizers.getIfAvailable());
}
.......
}
这是一个@Configuration配置类,包含@Bean的方法的返回值会注册为一个bean
在这个类和方法上我们看到很多条件配置注解
条件配置主要的注解是@Conditional,这个注解指定一个实现了Condition的类,类中实现了matchs方法,如果方法返回true,被@Conditional修饰的类或者方法才会创建bean。为了方便Spring4中已经帮我们实现了一些常用的条件配置注解
@ConditionalOnBean
@ConditionalOnClass
@ConditionalOnExpression
@ConditionalOnMissingBean
@ConditionalOnMissingClass
@ConditionalOnNotWebApplication
至此,我们已经分析了SpringBoot中自动化配置的基本原理,接下来我们会编写一个spring-boot-starter
SpringBoot自动配置的魔法的更多相关文章
- SpringBoot自动配置的魔法是怎么实现的
SpringBoot 最重要的功能就是自动配置,帮我们省去繁琐重复地配置工作.相信用过SpringBoot的人,都会被它简洁的步骤所惊讶.那么 SpringBoot 是如何实现自动配置的呢? 在这之前 ...
- SpringBoot自动配置源码调试
之前对SpringBoot的自动配置原理进行了较为详细的介绍(https://www.cnblogs.com/stm32stm32/p/10560933.html),接下来就对自动配置进行源码调试,探 ...
- SpringBoot实战之SpringBoot自动配置原理
SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...
- springboot自动配置源码解析
springboot版本:2.1.6.RELEASE SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfig ...
- 源码学习系列之SpringBoot自动配置(篇一)
源码学习系列之SpringBoot自动配置源码学习(篇一) ok,本博客尝试跟一下Springboot的自动配置源码,做一下笔记记录,自动配置是Springboot的一个很关键的特性,也容易被忽略的属 ...
- 源码学习系列之SpringBoot自动配置(篇二)
源码学习系列之SpringBoot自动配置(篇二)之HttpEncodingAutoConfiguration 源码分析 继上一篇博客源码学习系列之SpringBoot自动配置(篇一)之后,本博客继续 ...
- Springboot 自动配置浅析
Introduction 我们知道,SpringBoot之所以强大,就是因为他提供了各种默认的配置,可以让我们在集成各个组件的时候从各种各样的配置文件中解放出来. 拿一个最普通的 web 项目举例.我 ...
- SpringBoot自动配置原理学习
介绍 构建Springboot项目时我们会创建一个启动类 @SpringBootApplication public class DemoApplication { public static voi ...
- springboot自动配置国际化失效分析
最近在整理springBoot国际化时,发现国际化没有生效,通过报错提示在 MessageTag -> doEndTag处打断点 最后发现messageSource并不是ResourceBund ...
随机推荐
- Python_闭包
闭包并不只是一个python中的概念,在函数式编程语言中应用较为广泛.理解python中的闭包一方面是能够正确的使用闭包,另一方面可以好好体会和思考闭包的设计思想. 1.概念介绍 首先看一下维基上对闭 ...
- Java安全之Spring内存马
Java安全之Spring内存马 基础知识 Bean bean 是 Spring 框架的一个核心概念,它是构成应用程序的主干,并且是由 Spring IoC 容器负责实例化.配置.组装和管理的对象. ...
- Java 中如何实现线程间通信
世界以痛吻我,要我报之以歌 -- 泰戈尔<飞鸟集> 虽然通常每个子线程只需要完成自己的任务,但是有时我们希望多个线程一起工作来完成一个任务,这就涉及到线程间通信. 关于线程间通信本文涉及到 ...
- css中两种居中方式text-align:center和margin:0 auto 的使用场景
关于使用text-align:center和margin:0 auto 两种居中方式的比较 前言:最近由于要学习后端,需要提前学习一部分前端知识,补了补css知识,发现狂神在讲这一部分讲的不是特别清楚 ...
- [Keil 学习] printf, scanf函数的用法
C语言库函数中有一批"标准输入输出函数",它是以标准的输入输出设备(一般为终端设备)为输入输出对象的,其中用得比较多的是printf和scanf函数了. 在嵌入式设备中加入C语言的 ...
- java继承子类实例化过程(细节解释)
1 package face_08; 2 class Fu{ 3 Fu(){ 4 super(); 5 show(); 6 return; 7 } 8 void show() { 9 System.o ...
- Kubernetes的故事之持久化存储(十)
一.Storage 1.1.Volume 官网网址:https://kubernetes.io/docs/concepts/storage/volumes/ 通过官网说明大致总结下就是这个volume ...
- 回顾 Flutter 2021 重要时刻,奉上虎年红包封面喜迎新年!
2021 年,Flutter 正式进入 2.x 系列的正式版发布,年初的 Flutter 2 的发布 打开了一个新的"格局",为 Flutter 的加入了第五大特色--「可移植性」 ...
- plsql 存储过程 介绍。
/* 7-22 知识总结? 1. 存储过程 2.函数 3.包 */ /*1.什么是存储过程? 语法? 存储过程:类似于Java中的方法:完成一个特定的功能,一系列代码 (增删改操作和一些逻辑判断,se ...
- makefile快速入门
前言 在linux上开发c/c++代码,基本都会使用make和makefile作为编译工具.我们也可以选择cmake或qmake来代替,不过它们只负责生成makefile,最终用来进行编译的依然是ma ...