千家信息网

Spring Boot怎么排除自动加载数据源

发表于:2024-10-07 作者:千家信息网编辑
千家信息网最后更新 2024年10月07日,本篇内容介绍了"Spring Boot怎么排除自动加载数据源"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有
千家信息网最后更新 2024年10月07日Spring Boot怎么排除自动加载数据源

本篇内容介绍了"Spring Boot怎么排除自动加载数据源"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

前言

有些老项目使用Spring MVC里面有写好的数据库连接池,比如redis/mongodb/mybatis(mysql其他Oracle同理)。在这些项目迁入spring boot框架时,会报错。

原因是我们业务写好了连接池,但spring boot在jar包存在的时候会主动加载spring boot的autoconfiguration创建连接池,但我们并未配置Spring Boot参数,也不需要配置。

1. mongodb

mongodb自动配置错误如下:

org.mongodb.driver.cluster : Exception in monitor thread while connecting to server localhost:27017
com.mongodb.MongoSocketOpenException: Exception opening socket
Caused by: java.net.ConnectException: Connection refused (Connection refused)

但是我没有引入spring-boot-starter-data-mongodb的jar包,后来发现我引入了spring-data-mongodb的jar

检查spring-boot-starter-data-mongodb的jar,包括3部分,如下:

我的jar包都有,相当于这些jar拼装成了 spring-boot-starter-data-mongodb

在Spring Boot中自动引入了自动配置功能

需要手动排除自动配置的数据源,在SpringBootApplication中exclude

@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})

启动不再报错连接localhost:27017,业务正常。原理见Spring Boot官方文档

2. mybatis

mybatis同理

Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified and no embedded data

***************************
APPLICATION FAILED TO START
***************************

Description:

Cannot determine embedded database driver class for database type NONE

Action:

If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).

需要排除

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

3. 原理讲解

原理是EnableAutoConfiguration

进一步跟踪:

AutoConfigurationImportSelector这个类有自动加载与排除的逻辑

public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}

注意加载代码

getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
/**         * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}         * of the importing {@link Configuration @Configuration} class.         * @param autoConfigurationMetadata the auto-configuration metadata         * @param annotationMetadata the annotation metadata of the configuration class         * @return the auto-configurations that should be imported         */        protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,                        AnnotationMetadata annotationMetadata) {                if (!isEnabled(annotationMetadata)) {                        return EMPTY_ENTRY;                }                AnnotationAttributes attributes = getAttributes(annotationMetadata);                List configurations = getCandidateConfigurations(annotationMetadata, attributes);                configurations = removeDuplicates(configurations);                Set exclusions = getExclusions(annotationMetadata, attributes);                checkExcludedClasses(configurations, exclusions);                configurations.removeAll(exclusions);                configurations = filter(configurations, autoConfigurationMetadata);                fireAutoConfigurationImportEvents(configurations, exclusions);                return new AutoConfigurationEntry(configurations, exclusions);        }

里面

getExclusions(annotationMetadata, attributes);
/**         * Return any exclusions that limit the candidate configurations.         * @param metadata the source metadata         * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation         * attributes}         * @return exclusions or an empty set         */        protected Set getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {                Set excluded = new LinkedHashSet<>();                excluded.addAll(asList(attributes, "exclude"));                excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));                excluded.addAll(getExcludeAutoConfigurationsProperty());                return excluded;        }

看到了,exclude或者excludeName,当然还有一种方法

private List getExcludeAutoConfigurationsProperty() {                if (getEnvironment() instanceof ConfigurableEnvironment) {                        Binder binder = Binder.get(getEnvironment());                        return binder.bind(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class).map(Arrays::asList)                                        .orElse(Collections.emptyList());                }                String[] excludes = getEnvironment().getProperty(PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE, String[].class);                return (excludes != null) ? Arrays.asList(excludes) : Collections.emptyList();        }

通过application.properties文件配置spring.autoconfigure.exclude

private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";

"Spring Boot怎么排除自动加载数据源"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0