Spring Boot开箱即用,自动默认配置的工作原理

Spring Boot提供了很多”开箱即用“的依赖模块,都是以spring-boot-starter-xx作为命名的。例如, spring-boot-starter-redis、spring-boot-starter-data-mongodb、spring-boot-starter-data-elasticsearch 等。

Spring Boot 的开箱即用是一个很棒的设计,给开发者带来很大的便利。开发者只要在 Maven 的 pom 文件中添加相关依赖后,Spring Boot 就会针对这个应用自动创建和注入需要的 Spring Bean 到上下文中。

现在,我们通过源码深入分析下 Spring Boot 的实现原理吧。大笑

自动注入的核心在于 spring-boot-autoconfigure.jar 这个类库。在分析之前,我们先来看几个文件。吐舌头

@Configuration
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
@EnableConfigurationProperties
public class RedisAutoConfiguration {}
@Configuration
@ConditionalOnClass({ Mongo.class, MongoRepository.class })
@ConditionalOnMissingBean({ MongoRepositoryFactoryBean.class,
    MongoRepositoryConfigurationExtension.class })
@ConditionalOnProperty(prefix = "spring.data.mongodb.repositories", 
    name = "enabled", havingValue = "true", matchIfMissing = true)
@Import(MongoRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(MongoDataAutoConfiguration.class)
public class MongoRepositoriesAutoConfiguration {}

@Configuration
@ConditionalOnClass({ Client.class, TransportClientFactoryBean.class,
    NodeClientFactoryBean.class })
@EnableConfigurationProperties(ElasticsearchProperties.class)
public class ElasticsearchAutoConfiguration implements DisposableBean {}

上面三个源码分别对应Redis、MongoDB、ElasticSearch。通过对比,我们会发现它们都有一个特点,都存在 @ConditionalOnClass 注解。这个注解就是问题的关键所在。

@ConditionalOnClass 是什么作用呢?我们先来大概理解下面的代码。


源码中的方法主要是是将 @ConditionalOnClass 的参数中对应的类进行查询和匹配。

那么,查询的目的是什么呢?查询的目的在于, @ConditionalOnClass 参数中对应的类在 classpath 目录下存在时,才会去解析对应的配置类,否则不解析该注解修饰的配置类。

如下例子:

我们以 FreeMarker 的自动配置为例,重点讲解工作原理与加载过程。因为 FreeMarker 相对而言比较简单,Spring Boot 源码中只有三个类,所以作为案例相对而言比较好理解。

扫描二维码关注公众号,回复: 2261411 查看本文章

EnableAutoConfiguration 帮助我们做了什么?

你还记得 @EnableAutoConfiguration 注解么?

我们先来回顾下。

@RestController
@EnableAutoConfiguration
@ComponentScan(basePackages = { "com.lc.springboot" })
public class WebMain {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(WebMain.class, args);
    }
}

那么,现在我们剖析下 @EnableAutoConfiguration 的源码。

这里,关键在于 @Import 注解导入的 EnableAutoConfigurationImportSelector 类中最为关键的是 getCandidateConfigurations 方法中通过 SpringFactoriesLoader.loadFactoryNames 扫描  src/main/resources/ META-INF/spring.factories 中配置信息的spring.factories 文件。

现在,我们在来看下 SpringFactoriesLoader 源码。

突然,你是不是发现 spring.factories 文件是相当重要呢?对的,Spring Boot 通过扫描 src/main/resources/ META-INF/spring.factories 中配置信息,这个文件中的内容,判断有哪些自动配置。以 FreeMarker 为例,我们来看下它是如何配置的。

所以,Spring Boot 通过扫描 spring.factories 文件中的 EnableAutoConfiguration 参数中有哪些自动配置并进行加载。

配置参数类 – FreeMarkerProperties

这里的配置参数,可以通过application.properties 中直接设置。我们发现,它的前缀必须是 spring.freemarker。

自动配置类 – FreeMarkerAutoConfiguration

核心注解

有提到 @ConditionalOnClass 参数中对应的类在 classpath 目录下存在时,才会去解析对应的配置类,否则不解析该注解修饰的配置类。此外,还有一个主要的注解是 @EnableConfigurationProperties ,主要用来加载我们上面提到的配置参数类。

注入 Bean

这个源码非常好理解,我主要想讲2个注解。

第一注解是,@ConditionalOnMissingBean(name = “freeMarkerViewResolver”),指定当容器没有指定Bean的情况下的处理。

第二注解是,@ConditionalOnProperty,指定的属性是否有指定的值的处理,换句话说,如果在application.properties 没有配置,默认为 true,即条件符合。

总结:

       因此,Spring Boot 的开箱即用的实现原理,就很好简单,用一句话就可以概括了。Spring Boot 内部提供了很多自动化配置的类,例如,RedisAutoConfiguration 、MongoRepositoriesAutoConfiguration 、ElasticsearchAutoConfiguration , 这些自动化配置的类会判断 classpath 中是否存在自己需要的那个类,如果存在则会自动配置相关的配置,否则就不会自动配置,因此,开发者在 Maven 的 pom 文件中添加相关依赖后,Spring Boot 就会针对这个应用自动创建和注入需要的 Spring Bean 到上下文中。这些依赖就会下载很多 jar 包到 classpath 中 ,有了这些 lib 就会触发自动化配置,所以,我们就能很便捷地使用对于的模块功能了。

猜你喜欢

转载自blog.csdn.net/codertnt/article/details/81027391