SpringBoot排除不需要的自动配置类DataSourceAutoConfiguration问题

 更新时间:2024年07月11日 14:38:02   作者:山河锦绣  
这篇文章主要介绍了SpringBoot排除不需要的自动配置类DataSourceAutoConfiguration问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、排除自动配置类的三种方式

以下三种方式可以用来排除任意的自动配置类

1.1使用@SpringBootApplication注解排除

使用exclude属性(value是Class对象数组)

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

或者excludeName属性(value是类的全限定名字符串数组)

@SpringBootApplication(excludeName = {"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"})
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

1.2使用@EnableAutoConfiguration注解排除

1.在项目中创建一个配置类对象MyConfig.class,在配置类上使用@EnableAutoConfiguration注解。

使用exclude属性(value是Class对象数组)

@Configuration
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
public class MyConfig {
}

或者excludeName属性(value是类的全限定名字符串数组)

@Configuration
@EnableAutoConfiguration(excludeName = {"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"})
public class MyConfig {
}

思考1:为什么不能直接在启动类上使用@EnableAutoConfiguration注解,而要重新创建一个配置类?

因为@SpringBootApplication已经继承了@EnableAutoConfiguration,并且@EnableAutoConfiguration注解,是不可在类上重复使用的注解(换句话说就是使用@SpringBootApplication注解,就相当于使用了@EnableAutoConfiguration注解)

所以 我们会发现方法一与方法二本质上是一样的只是形式上的差别,底层都是依赖于@EnableAutoConfiguration注解实现的排除功能。

思考2:@SpringBootApplication注解与@EnableAutoConfiguration的关系?为什么在@SpringBootApplication注解中配置属性底层还是使用@EnableAutoConfiguration实现的呢?

@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 {

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	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
	 */
	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};

我们可以看出源码中使用了注解:

@AliasFor(annotation = EnableAutoConfiguration.class)

将@SpringBootApplication的exclude和excludeName属性与@EnableAutoConfiguration的属性做了一个桥接的作用。

1.3.在yml配置文件中添加排除配置

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

注:如果要排除多个类,使用逗号隔开

二、为什么可以这样排除,内在逻辑原理研究

springBoot将自动配置类添入到spring容器中的部分源码:

	protected AutoConfigurationEntry getAutoConfigurationEntry(
			AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return EMPTY_ENTRY;
		}
        //获取注解中配置的需要排除的自动配置类信息
		AnnotationAttributes attributes = getAttributes(annotationMetadata);
        //获取项目中所有的自动配置类
		List<String> configurations = getCandidateConfigurations(annotationMetadata,
				attributes);
		configurations = removeDuplicates(configurations);
        //获取配置文件中配置的需要排除的类信息,并与之前的注解中配置的数据整合在一起
		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
		checkExcludedClasses(configurations, exclusions);
        //将需要排除的类信息删除
		configurations.removeAll(exclusions);
		configurations = filter(configurations, autoConfigurationMetadata);
		fireAutoConfigurationImportEvents(configurations, exclusions);
        //返回最终需要的自动配置类
		return new AutoConfigurationEntry(configurations, exclusions);
	}
  • 1.这段代码中的主要逻辑就是,将项目中所有需要的自动配置类的全限定名以字符串数组返回出去,后续spring容器会将所有的配置类创建成Bean
  • 2.所以我们三种配置排除自动配置类的行为,最终都会在这段代码逻辑中体现出来,在spring容器初始化他们之前,我们就已经提前把他们从初始化的名单中排除了
  • 3.我们配置的时候为什么都是使用的类的全限定名在这里也得到了解释,因为只有使用全限定名spring容器才能将其创建成对象。
  • 4.还可以得出结论就是几种方式可以同时使用,最终排除的是他们的并集

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot中使用异步线程导致Request请求头丢失问题的解决方法

    SpringBoot中使用异步线程导致Request请求头丢失问题的解决方法

    异步线程请求头丢失的问题通常发生在多线程环境中,特别是在使用 CompletableFuture 或其他异步编程模型时,本文给大家详细介绍了SpringBoot中使用异步线程导致Request请求头丢失问题的原因和解决方法,需要的朋友可以参考下
    2025-07-07
  • Java中object类常用方法及应用场景详解

    Java中object类常用方法及应用场景详解

    这篇文章主要介绍了Java中object类常用方法及应用场景的相关资料,正确重写这些方法是面向对象设计的基本要求,有助于避免踩坑并提高代码质量,需要的朋友可以参考下
    2025-04-04
  • ConcurrentHashMap线程安全及实现原理实例解析

    ConcurrentHashMap线程安全及实现原理实例解析

    这篇文章主要介绍了ConcurrentHashMap线程安全及实现原理实例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Java导致内存泄漏的多种情况分析

    Java导致内存泄漏的多种情况分析

    本文介绍了Java中常见的内存泄漏情况,包括生命周期长的集合、未关闭的资源连接、ThreadLocal使用不当、内部类与外部类引用非静态内部类、监听器与回调注册后没有注销,推荐使用MAT和VisualVM等工具进行内存泄漏排查,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • 使用MyBatis返回其它类对象的字段处理

    使用MyBatis返回其它类对象的字段处理

    这篇文章主要介绍了使用MyBatis返回其它类对象的字段处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Java高效处理超大文本文件的技巧分享

    Java高效处理超大文本文件的技巧分享

    这篇文章主要介绍了Java处理超大文本文件的几种方式,包括BufferedReader逐行读取、Files.lines()流式处理、内存映射文件、分块读取等,并提供了每种方法的优缺点和适用场景,最终推荐使用BufferedReader方案处理超大文本文件,需要的朋友可以参考下
    2025-11-11
  • JAVA中使用FileWriter写数据到文本文件步骤详解

    JAVA中使用FileWriter写数据到文本文件步骤详解

    这篇文章主要介绍了JAVA中使用FileWriter写数据到文本文件步骤详解,FileWriter类提供了多种写入字符的方法,包括写入单个字符、写入字符数组和写入字符串等,它还提供了一些其他的方法,如刷新缓冲区、关闭文件等,需要的朋友可以参考下
    2023-10-10
  • Springboot项目中kaptcha验证码的使用方式

    Springboot项目中kaptcha验证码的使用方式

    这篇文章主要介绍了Springboot项目中kaptcha验证码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Java SPI机制详细介绍

    Java SPI机制详细介绍

    大家好,本篇文章主要讲的是Java SPI机制详细介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

    Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

    这篇文章主要介绍了Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单,本文给大家介绍的非常详细,需要的朋友可以参考下
    2025-01-01

最新评论