Spring?Boot如何排除自動加載數(shù)據(jù)源
前言
有些老項目使用Spring MVC里面有寫好的數(shù)據(jù)庫連接池,比如redis/mongodb/mybatis(mysql其他Oracle同理)。在這些項目遷入spring boot框架時,會報錯。
原因是我們業(yè)務(wù)寫好了連接池,但spring boot在jar包存在的時候會主動加載spring boot的autoconfiguration創(chuàng)建連接池,但我們并未配置Spring Boot參數(shù),也不需要配置。
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包,后來發(fā)現(xiàn)我引入了spring-data-mongodb的jar
檢查spring-boot-starter-data-mongodb的jar,包括3部分,如下:
我的jar包都有,相當于這些jar拼裝成了 spring-boot-starter-data-mongodb
在Spring Boot中自動引入了自動配置功能
需要手動排除自動配置的數(shù)據(jù)源,在SpringBootApplication中exclude
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
啟動不再報錯連接localhost:27017,業(yè)務(wù)正常。原理見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<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); }
里面
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<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) { Set<String> excluded = new LinkedHashSet<>(); excluded.addAll(asList(attributes, "exclude")); excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName"))); excluded.addAll(getExcludeAutoConfigurationsProperty()); return excluded; }
看到了,exclude或者excludeName,當然還有一種方法
private List<String> 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";
總結(jié)
出現(xiàn)這種錯誤多半發(fā)生在引入了spring-boot-starter-mongodb等這樣的starter插件jar,沒有配置數(shù)據(jù)源url;或者舊業(yè)務(wù)升級spring boot(筆者就是這種情況)
解決方法
不需要的jar不要引入即可解決問題
使用exclude排除,有三種實現(xiàn)方式exclude、excludeName、spring.autoconfigure.exclude
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java中Double、Float類型的NaN和Infinity的具體使用
Java在處理浮點數(shù)運算時,提供了NaN和Infinity兩個常量,本文主要介紹了Java中Double、Float類型的NaN和Infinity的具體使用,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06IDEA插件EasyCode及MyBatis最優(yōu)配置步驟詳解
這篇文章主要介紹了IDEA插件EasyCode MyBatis最優(yōu)配置步驟詳解,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12使用Java和SpringBoot實現(xiàn)服務(wù)器發(fā)送事件(Server-Sent Events)
使用Java開發(fā)web應(yīng)用,大多數(shù)時候我們提供的接口返回數(shù)據(jù)都是一次性完整返回,有些時候,我們也需要提供流式接口持續(xù)寫出數(shù)據(jù),以下提供一種簡單的方式,本文給大家介紹了如何在Java web中實現(xiàn)服務(wù)器發(fā)送事件,需要的朋友可以參考下2024-02-02IDEA?2020.3最新永久激活碼(免費激活到?2099?年,親測有效)
分享一下?IntelliJ?IDEA?2020.3.1?最新激活注冊碼,破解教程如下,可免費激活至?2099?年,親測有效,本文給大家分享兩種方法,感興趣的朋友參考下吧2021-01-01springboot中如何使用openfeign進行接口調(diào)用
這篇文章主要介紹了springboot中如何使用openfeign進行接口調(diào)用問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07