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.还可以得出结论就是几种方式可以同时使用,最终排除的是他们的并集
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。