SpringBoot排除自動(dòng)加載數(shù)據(jù)源方式
前言
有些老項(xiàng)目使用Spring MVC里面有寫(xiě)好的數(shù)據(jù)庫(kù)連接池,比如redis/mongodb/mybatis(mysql其他Oracle同理)。
在這些項(xiàng)目遷入spring boot框架時(shí),會(huì)報(bào)錯(cuò)。
原因是我們業(yè)務(wù)寫(xiě)好了連接池,但spring boot在jar包存在的時(shí)候會(huì)主動(dòng)加載spring boot的autoconfiguration創(chuàng)建連接池,但我們并未配置Spring Boot參數(shù),也不需要配置。
1. mongodb
mongodb自動(dòng)配置錯(cuò)誤如下:
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)
但是我沒(méi)有引入spring-boot-starter-data-mongodb的jar包,后來(lái)發(fā)現(xiàn)我引入了spring-data-mongodb的jar
檢查spring-boot-starter-data-mongodb的jar,包括3部分,如下:
我的jar包都有,相當(dāng)于這些jar拼裝成了 spring-boot-starter-data-mongodb
在Spring Boot中自動(dòng)引入了自動(dòng)配置功能
需要手動(dòng)排除自動(dòng)配置的數(shù)據(jù)源,在SpringBootApplication中exclude
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
啟動(dòng)不再報(bào)錯(cuò)連接localhost:27017,業(yè)務(wù)正常。
原理見(jiàn)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
進(jìn)一步跟蹤:
AutoConfigurationImportSelector這個(gè)類(lèi)有自動(dòng)加載與排除的邏輯
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,當(dāng)然還有一種方法
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(); }
通過(guò)application.properties文件配置spring.autoconfigure.exclude
private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
總結(jié)
出現(xiàn)這種錯(cuò)誤多半發(fā)生在引入了spring-boot-starter-mongodb等這樣的starter插件jar,沒(méi)有配置數(shù)據(jù)源url;或者舊業(yè)務(wù)升級(jí)spring boot(筆者就是這種情況)
解決方法:
不需要的jar不要引入即可解決問(wèn)題
使用exclude排除,有三種實(shí)現(xiàn)方式exclude、excludeName、spring.autoconfigure.exclude
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot配置多個(gè)數(shù)據(jù)源超簡(jiǎn)單步驟(連接多個(gè)數(shù)據(jù)庫(kù))
- springboot Jpa多數(shù)據(jù)源(不同庫(kù))配置過(guò)程
- SpringBoot實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的項(xiàng)目實(shí)踐
- Springboot如何設(shè)置多數(shù)據(jù)源,隨時(shí)切換
- SpringBoot動(dòng)態(tài)數(shù)據(jù)源連接測(cè)試的操作詳解
- SpringBoot集成Druid實(shí)現(xiàn)多數(shù)據(jù)源的兩種方式
相關(guān)文章
Java日期時(shí)間字符串和毫秒相互轉(zhuǎn)換的方法
這篇文章主要為大家詳細(xì)介紹了Java日期時(shí)間字符串和毫秒相互轉(zhuǎn)換的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Springboot接收POST請(qǐng)求,數(shù)據(jù)為json類(lèi)型問(wèn)題
在使用Spring框架中,當(dāng)處理POST請(qǐng)求且內(nèi)容為JSON類(lèi)型時(shí),應(yīng)使用@RequestBody注解而非@RequestParam,通過(guò)@RequestBody可以將JSON數(shù)據(jù)綁定到一個(gè)Map對(duì)象中,然后通過(guò)Map的get方法來(lái)獲取需要的參數(shù)2022-10-10springboot如何通過(guò)URL方式訪(fǎng)問(wèn)外部資源
這篇文章主要介紹了springboot如何通過(guò)URL方式訪(fǎng)問(wèn)外部資源,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Netty分布式Server啟動(dòng)流程服務(wù)端初始化源碼分析
本章主要講解server啟動(dòng)的關(guān)鍵步驟,?讀者只需要了解server啟動(dòng)的大概邏輯,?知道關(guān)鍵的步驟在哪個(gè)類(lèi)執(zhí)行即可,?并不需要了解每一步的運(yùn)作機(jī)制,?之后會(huì)對(duì)每個(gè)模塊進(jìn)行深度分析2022-03-03SpringCloud微服務(wù)網(wǎng)關(guān)限流方式
這篇文章主要介紹了SpringCloud微服務(wù)網(wǎng)關(guān)限流方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08一篇文章教你使用枚舉來(lái)實(shí)現(xiàn)java單例模式
本篇文章主要介紹了Java實(shí)現(xiàn)單例的3種普遍的模式,餓漢式、懶漢式、枚舉式。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助2021-07-07java多線(xiàn)程并發(fā)executorservice(任務(wù)調(diào)度)類(lèi)
這篇文章主要介紹了線(xiàn)程并發(fā)ScheduledExecutorService類(lèi),設(shè)置 ScheduledExecutorService ,2秒后,在 1 分鐘內(nèi)每 10 秒鐘蜂鳴一次2014-01-01SpringBoot參數(shù)校驗(yàn)的方法總結(jié)
今天帶大家學(xué)習(xí)SpringBoot參數(shù)校驗(yàn)的方法,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05