Spring Boot如何排除自动加载数据源

网友投稿 291 2022-09-09


Spring Boot如何排除自动加载数据源

目录前言1. mongodb2. mybatis3. 原理讲解总结解决方法

前言

有些老项目使用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 {@lisPDtGZnk 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 http://static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";

总结

出现这种错误多半发生在引入了spring-boot-starter-mongodb等这样的starter插件jar,没有配置数据源url;或者旧业务升级spring boot(笔者就是这种情况)

解决方法

不需要的jar不要引入即可解决问题

使用exclude排除,有三种实现方式exclude、excludeName、spring.autoconfigure.exclude


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:ASA多区域实验案例
下一篇:IPv6协议实验案例(ipv6相关协议)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~