Spring Boot 自动配置的实现
作者:David_jim 发布时间:2023-07-21 18:18:55
Spring Boot 自动配置
来看下 spring boot中自动配置的注解
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
exclude() 可以排除一些自动配置的内容
excludeName 通过名称排除自动配置内容
再来看下, @EnableAutoConfiguration
是怎么处理自动配置的呢?
注意到@Import(EnableAutoConfigurationImportSelector.class)
public class EnableAutoConfigurationImportSelector
extends AutoConfigurationImportSelector {
@Override
protected boolean isEnabled(AnnotationMetadata metadata) {
if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
return getEnvironment().getProperty(
EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
true);
}
return true;
}
}
}
再来看下 AutoConfigurationImportSelector
,主要是 接口的 ImportSelector
的实现
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
//1、 自动配置的元数据 spring-autocomfigure-metadata.properties
// 自动配置的开启条件
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 获取设置的自动配置列表 spring.factories
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
// 获取要排除的自动配置列表,可以通过 注解@EnableAutoConfiguration 的exclude和
// 配置文件设置 spring.autoconfigure.exclude key的值
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 通过 spring-autocomfigure-metadata.properties ConditionOnClass 条件进行过滤
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
看下 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.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
再看下 spring framework中 ConfigurationClassParser
的处理方式,会解析 @Import
里的接口 ImportSelector
返回的所有配置类,那是怎么配置的呢,如 JpaRepositoriesAutoConfiguration
@Configuration
@ConditionalOnBean(DataSource.class)
@ConditionalOnClass(JpaRepository.class)
@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class,
JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
@Import(JpaRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
public class JpaRepositoriesAutoConfiguration {
}
从上面可以看到,有很多的@ConditionalOn**
的注解,我们来看下 ConditionEvaluator
这个 条件计算器,会去计算出当前这个配置类 是否要开启,而这些 @ConditionalOn**
是依赖于 @Conditional
这个注解,如 @ConditionalOnBean
最终是通过 Condition 接口来作条件选择
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {
/**
* The class type of bean that should be checked. The condition matches when any of
* the classes specified is contained in the {@link ApplicationContext}.
* @return the class types of beans to check
*/
Class<?>[] value() default {};
/**
* The class type names of bean that should be checked. The condition matches when any
* of the classes specified is contained in the {@link ApplicationContext}.
* @return the class type names of beans to check
*/
String[] type() default {};
/**
* The annotation type decorating a bean that should be checked. The condition matches
* when any of the annotations specified is defined on a bean in the
* {@link ApplicationContext}.
* @return the class-level annotation types to check
*/
Class<? extends Annotation>[] annotation() default {};
/**
* The names of beans to check. The condition matches when any of the bean names
* specified is contained in the {@link ApplicationContext}.
* @return the name of beans to check
*/
String[] name() default {};
/**
* Strategy to decide if the application context hierarchy (parent contexts) should be
* considered.
* @return the search strategy
*/
SearchStrategy search() default SearchStrategy.ALL;
}
Spring boot 的autoconfigure 是囊括了所有可以和spring 整合的项目,但大部分情况下,并不是所以的项目都会启用,通过 Condition和@Conditional 来判断条件
判断classPath 是否存在指定的类
@ConditionalOnClass
判断 ApplicationContext 中是否存在指定的 Bean
@ConditionalOnBean
配置环境中是否存在特定的配置项
@ConditionalOnProperty
配置环境中指定的配置项是否存在指定的值
禁用配置
当前 也是可以禁用某些我们不想要的默认配置,如上面加载时说到,会排除一些配置(exclude)
设置
@EnableAutoConfiguration
的exclude 配置在配置文件增加 spring.autoconfigure.exclude 配置
来源:https://www.jianshu.com/p/7261521394e7


猜你喜欢
- 多线程的好处是不言而喻的,它能帮我们刚更多的事情,同时干不同的事情在程序设计中是经常出现的,这种时候我们使用的是线程。在Kotlin 中,
- 安卓虽然已经成为了移动设备第一操作系统,且影响力也延伸到了汽车和tv端,不过对于谷歌来说,需要依靠Java来做安卓开发一直是一个心病,因为O
- intellij idea是一款非常优秀的软件开发工具,它拥有这强大的插件体系,可以帮助开发者完成很多重量级的功能。今天,我们来学习一下如何
- Lambda 表达式Lambda 表达式是现代 C++ 中最重要的特性之一,而 Lambda 表达式,实际上就是提供了一个类似匿名函数的特性
- 本文基于ThreadLocal原理,实现了一个上下文状态管理组件Scope,通过开启一个自定义的Scope,在Scope范围内,可以通过Sc
- 为了让大家知道下面内容是否是自己想要的,我先发效果图。好了,那就开始贴代码了以下为一个按钮的事件,为裁剪准备图片、裁剪路径、保存路径priv
- 下载动画经常出现在下载需求多的app中,比如游戏下载平台,应用市场……先看看效果图:实现private void startAnim() {
- 首先,来看一下,快速排序的实现的动态图:快速排序介绍:快速排序,根据教科书说法来看,是冒泡排序的一种改进。快速排序,由一个待排序的数组(ar
- 导出excel是咱Java开发的必备技能啦,之前项目有这个功能,现在将其独立出来,分享一下。所用技术就是SpringBoot,然后是MVC架
- 1、普通用户与系统管理员用户的权限要有严格的区分。如果一个普通用户在使用查询语句中嵌入另一个Drop Table语句,那么是否允许
- 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。包的作用1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用
- textField用于文本输入,它提供了很多属性:const TextField({ ... TextEditi
- 一、使用JDK生成WSDL的对象类1、cmd进入JDK的bin文件中执行命令 wsimport -keep -p com.demo.clie
- 近年来,二维码的使用越来越风生水起,笔者最近手头也遇到了一个需要使用二维码扫码登录网站的活,所以研究了一下这一套机制,并用代码实现了整个流程
- 简要DecimalFormat 的 pattern 都包含着 正负子 pattern ,例如 “#,##0.00;(#,##0.00)”:/
- 本文实例讲述了Windows窗体的.Net框架绘图技术实现方法,非常实用,具体内容如下:一般来说,当编写一个典型的Windows 窗体程序时
- Spring Boot 内置Tomcat默认端口号为8080,在开发多个应用调试时很不方便,本文介绍了修改 Spring Boot
- 一、strcmp函数适用对象char*类型字符串函数介绍strcmp函数是cstring库中的函数,包含在string.h头文件中用法str
- 1. selectKey标签查询DDLCREATE TABLE `luck_reward_info` ( `id` int NO
- 这篇文章主要介绍了spring强行注入和引用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友