Spring Boot 2.x 实践记:@SpringBootTest

本文介绍如何使用@SpringBootTest注解在SpringBoot中进行集成测试和单元测试。详细解释了@SpringBootTest的工作原理,包括根据包结构扫描内容、加载外部配置及运行自动配置的启动器。并通过示例代码展示了如何指定特定的服务进行测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

  • @SpringBootTest
  • 用@SpringBootTest集成测试
  • 用@SpringBootTest单元测试
  • 小结

TL;DR

Spring Boot 中做测试,默认使用 @SpringBootTest 注解,今天我们就来快速学习如何进行单元测试或集成测试。

1. @SpringBootTest

运行Sprng Boot 测试,只需要在测试类上指定 @SpringBootTest,它的类声明如下:
在这里插入图片描述
写Spring Boot的测试类时一定要注意:启动类的位置,因为 @SpringBootTest 会优先搜索当前目录及其子目录。

在老的 spring-test 中,我们通常使用@ContextConfiguration(classes=…​)注解来获得测试时的上下文Context信息,而在Spring Boot Test 中都是通过@SpringBootTest来自动完成的。

2. 用@SpringBootTest集成测试

其实,@SpringBootTest 的原理就是模仿由 Spring Boot 框架提供的运行时上下文,比如:

  • 根据包结构决定要扫描哪些内容
  • 从预定义的位置加载外部配置
  • 可选地运行自动配置的启动器等

所以编写的测试类其实很简单,如下代码示例:

@SpringBootTest
public class SpringBootDemoApplicationTests 
{   
    //---- tests -----
}

3. 用@SpringBootTest单元测试

3.1. classes 属性

除了加载所有的服务外,我们在很多时候希望能更精准的进行指定服务的测试,这时我们就会用到classes属性,用来指定用于加载 ApplicationContext 里的特定类(注意:需要是实现类,而不是接口类)。

@SpringBootTest(classes = {TestManDaoImpl.class,TestManServiceImpl.class})
public class SpringBootDemoApplicationTests 
{   
    @Resource
    private TestManService testManService;
    
    //---- tests -----
}

3.2. *…Test 相关注解

除了 @SpringBootTest 注解外,Spring Boot 还提供了很多特定注解来帮助我们快速完成测试。

不过,这些注解可能会禁用自动配置,使用时需要仔细阅读说明。

更多详情,参看:Spring Boot Features Testing

4. 结论

到此,我们已经能使用@SpringBootTest注解来对Spring Boot应用编写集成测试或单元测试。

欢迎留言。

2025-06-06T00:24:36.793+08:00 ERROR 39188 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLICATION FAILED TO START *************************** Description: Failed to bind properties under 'spring.datasource.type' to java.lang.Class<javax.sql.DataSource>: Property: spring.datasource.type Value: "com.alibaba.druid.pool.DruidDataSource" Origin: class path resource [application.yml] - 7:11 Reason: failed to convert java.lang.String to java.lang.Class<javax.sql.DataSource> (caused by java.lang.ClassNotFoundException: com.alibaba.druid.pool.DruidDataSource) Action: Update your application's configuration 2025-06-06T00:24:36.795+08:00 WARN 39188 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener] to prepare test instance [com.itheima.springboot_profile.SpringbootProfileApplicationTests@2cd388f5] java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@16132f21 testClass = com.itheima.springboot_profile.SpringbootProfileApplicationTests, locations = [], classes = [com.itheima.springboot_profile.SpringbootProfileApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@130c12b7, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@70e9c95d, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@45099dd3, org.springframework.boot.test.web.reactor.netty.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory$DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer@2e385cce, org.springframework.boot.test.autoconfigure.OnFailureConditionReportContextCustomizerFactory$OnFailureConditionReportContextCustomizer@2a7f1f10, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@202b0582, org.springframework.boot.test.context.SpringBootTestAnnotation@d09d9319], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null] at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:180) ~[spring-test-6.1.20.jar:6.1.20] at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:130) ~[spring-test-6.1.20.jar:6.1.20] at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:191) ~[spring-test-6.1.20.jar:6.1.20] at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:130) ~[spring-test-6.1.20.jar:6.1.20] at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260) ~[spring-test-6.1.20.jar:6.1.20] at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:163) ~[spring-test-6.1.20.jar:6.1.20] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$10(ClassBasedTestDescriptor.java:378) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:383) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$11(ClassBasedTestDescriptor.java:378) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na] at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na] at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na] at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310) ~[na:na] at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735) ~[na:na] at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734) ~[na:na] at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762) ~[na:na] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:377) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:290) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:289) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:279) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at java.base/java.util.Optional.orElseGet(Optional.java:364) ~[na:na] at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:278) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:106) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:105) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:69) ~[junit-jupiter-engine-5.10.5.jar:5.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:128) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:128) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.10.5.jar:1.10.5] at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na] at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:160) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:146) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:144) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:143) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:100) ~[junit-platform-engine-1.10.5.jar:1.10.5] at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na] at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:160) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:146) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:144) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:143) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:100) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) ~[junit-platform-engine-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:198) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:169) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:93) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:58) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:141) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:57) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:103) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:85) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:63) ~[junit-platform-launcher-1.10.5.jar:1.10.5] at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71) ~[junit5-rt.jar:na] at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) ~[junit-rt.jar:na] at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221) ~[junit-rt.jar:na] at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) ~[junit-rt.jar:na] Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Generic.class]: Unsatisfied dependency expressed through method 'dataSource' parameter 0: Error creating bean with name 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties': Could not bind properties to 'DataSourceProperties' : prefix=spring.datasource, ignoreInvalidFields=false, ignoreUnknownFields=true at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.20.jar:6.1.20] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.20.jar:6.1.20] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:145) ~[spring-boot-test-3.3.12.jar:3.3.12] at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58) ~[spring-core-6.1.20.jar:6.1.20] at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46) ~[spring-core-6.1.20.jar:6.1.20] at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1464) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:564) ~[spring-boot-test-3.3.12.jar:3.3.12] at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:145) ~[spring-boot-test-3.3.12.jar:3.3.12] at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:116) ~[spring-boot-test-3.3.12.jar:3.3.12] at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225) ~[spring-test-6.1.20.jar:6.1.20] at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152) ~[spring-test-6.1.20.jar:6.1.20] ... 70 common frames omitted Caused by: org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties': Could not bind properties to 'DataSourceProperties' : prefix=spring.datasource, ignoreInvalidFields=false, ignoreUnknownFields=true at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:99) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:79) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1798) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1448) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1358) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782) ~[spring-beans-6.1.20.jar:6.1.20] ... 94 common frames omitted Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.datasource.type' to java.lang.Class<javax.sql.DataSource> at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:391) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:354) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:477) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:99) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:87) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:63) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$6(Binder.java:480) ~[spring-boot-3.3.12.jar:3.3.12] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na] at java.base/java.util.AbstractList$RandomAccessSpliterator.tryAdvance(AbstractList.java:706) ~[na:na] at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na] at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647) ~[na:na] at org.springframework.boot.context.properties.bind.Binder.fromDataObjectBinders(Binder.java:488) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$7(Binder.java:479) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:597) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:583) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:479) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:418) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:350) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:339) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:269) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:256) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:94) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:96) ~[spring-boot-3.3.12.jar:3.3.12] ... 108 common frames omitted Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.lang.Class<javax.sql.DataSource>] for value [com.alibaba.druid.pool.DruidDataSource] at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) ~[spring-core-6.1.20.jar:6.1.20] at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:182) ~[spring-core-6.1.20.jar:6.1.20] at org.springframework.boot.context.properties.bind.BindConverter.convert(BindConverter.java:110) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.BindConverter.convert(BindConverter.java:101) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.BindConverter.convert(BindConverter.java:93) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bindProperty(Binder.java:463) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:407) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:350) ~[spring-boot-3.3.12.jar:3.3.12] ... 134 common frames omitted Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Class'; Could not find class [com.alibaba.druid.pool.DruidDataSource] at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:87) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:71) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.boot.context.properties.bind.BindConverter$TypeConverterConverter.convert(BindConverter.java:229) ~[spring-boot-3.3.12.jar:3.3.12] at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-6.1.20.jar:6.1.20] ... 141 common frames omitted Caused by: java.lang.IllegalArgumentException: Could not find class [com.alibaba.druid.pool.DruidDataSource] at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:355) ~[spring-core-6.1.20.jar:6.1.20] at org.springframework.beans.propertyeditors.ClassEditor.setAsText(ClassEditor.java:65) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:439) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:412) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:161) ~[spring-beans-6.1.20.jar:6.1.20] at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:80) ~[spring-beans-6.1.20.jar:6.1.20] ... 144 common frames omitted Caused by: java.lang.ClassNotFoundException: com.alibaba.druid.pool.DruidDataSource at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na] at java.base/java.lang.Class.forName0(Native Method) ~[na:na] at java.base/java.lang.Class.forName(Class.java:467) ~[na:na] at org.springframework.util.ClassUtils.forName(ClassUtils.java:304) ~[spring-core-6.1.20.jar:6.1.20] at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:345) ~[spring-core-6.1.20.jar:6.1.20] ... 149 common frames omitted
06-07
<think>我们正在解决SpringBoot3.3.12项目中使用Druid数据源时出现的`ClassNotFoundException:com.alibaba.druid.pool.DruidDataSource`错误。这个问题通常是由于项目依赖中没有正确引入Druid相关库导致的。根据引用[2]可知,SpringBoot3.3.12要求JDK17,并且我们使用Maven进行构建。因此,解决方案主要是添加正确的Druid依赖,并注意版本兼容性。步骤:1.添加DruidSpringBootStarter依赖。由于我们使用的是SpringBoot3.x,因此需要选择与SpringBoot3兼容的Druid版本。目前,DruidSpringBootStarter的1.3.0版本开始支持SpringBoot3.x。2.在pom.xml文件中添加如下依赖:```xml<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.3.0</version></dependency>```注意:如果使用SpringBoot2.x,我们使用的是`druid-spring-boot-starter`,但是为了兼容SpringBoot3,这里使用`druid-spring-boot-3-starter`。3.配置数据源:在application.properties或application.yml中配置Druid数据源。但是,由于我们使用了starter,所以很多配置可以自动完成,只需要配置基本的数据源信息即可。示例配置(application.properties):```propertiesspring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=falsespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver#启用Druid监控页面(可选)spring.datasource.druid.stat-view-servlet.enabled=true```4.如果遇到版本冲突问题,请检查是否已经正确引入了与SpringBoot3.3.12兼容的版本。Druid1.3.0版本是兼容SpringBoot3的。5.如果仍然出现类找不到的问题,请检查依赖是否下载成功,可以使用命令`mvndependency:tree`查看依赖树,确认druid相关的jar是否存在。另外,需要注意的是,如果之前使用的是传统的`com.alibaba.druid.pool.DruidDataSource`的配置方式,那么在SpringBoot3.x中,我们更推荐使用上面提到的starter方式,因为传统的配置方式可能需要手动注入DruidDataSource,并且需要排除SpringBoot的默认数据源。但是通过starter,这些步骤都可以省略。如果必须使用传统的非starter方式(例如需要高度自定义配置),那么可以添加如下依赖:```xml<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.3.0</version></dependency>```然后通过配置类来定义数据源,例如:```java@ConfigurationpublicclassDruidConfig{@Bean@ConfigurationProperties(prefix="spring.datasource")publicDataSourcedataSource(){returnnewDruidDataSource();}}```但是,推荐使用starter方式,因为它简化了配置。问题排查:-如果添加了依赖仍然报错,检查是否由于Maven仓库没有下载成功。可以尝试清除本地仓库中druid相关的目录,然后重新下载。-检查是否有多个版本的druid依赖冲突,可以通过`mvndependency:tree|grepdruid`查看。总结:主要原因是缺少Druid的依赖或者依赖版本不正确。添加正确的依赖即可解决。根据引用[1]中提到的类似问题(关于feignclient的fallbackFactory未找到),我们可以联想到可能是依赖配置的问题,需要检查依赖是否正确引入。引用[3]中提到的配置绑定问题在我们的场景中不适用,因此忽略。因此,解决方案的核心是添加与SpringBoot3兼容的Druidstarter依赖。---相关问题:1.如何配置Druid监控页面?2.Druid在SpringBoot3中如何配置多数据源?3.如何分析Druid连接池的性能?4.SpringBoot3中如何定制Druid数据源的过滤器和监听器?</think> ### 解决 Spring Boot 3.3.12 中 Druid 数据源的 ClassNotFoundException 问题 当在 Spring Boot 3.3.12 项目中遇到 `ClassNotFoundException: com.alibaba.druid.pool.DruidDataSource` 错误时,这是完整的解决方案: #### 1️⃣ **添加正确版本的 Druid 依赖** 在 `pom.xml` 中添加与 Spring Boot 3.3.12 兼容的 Druid 依赖(必须使用 Java 17 兼容版本): ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-3-starter</artifactId> <version>1.3.0</version> <!-- 专为 Spring Boot 3 设计 --> </dependency> ``` 📌 **关键说明**: - 避免使用过时的 `druid` 或 `druid-spring-boot-starter` - Spring Boot 3 必须使用 `druid-spring-boot-3-starter` 系列 - 最新验证兼容版本:`1.3.0` #### 2️⃣ **配置数据源属性** 在 `application.properties` 或 `application.yml` 中配置: ```properties # 基本配置 spring.datasource.url=jdbc:mysql://localhost:3306/your_db spring.datasource.username=root spring.datasource.password=your_password # 显式指定 Druid 数据源(必须!) spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # Druid 专有配置 spring.datasource.druid.initial-size=5 spring.datasource.druid.min-idle=5 spring.datasource.druid.max-active=20 ``` #### 3️⃣ **配置类示例(可选)** 如需自定义配置,添加配置类: ```java @Configuration public class DruidConfig { @Bean @ConfigurationProperties("spring.datasource.druid") public DataSource dataSource() { return DruidDataSourceBuilder.create().build(); } // 注册监控Servlet(可选) @Bean public ServletRegistrationBean<StatViewServlet> druidServlet() { ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); bean.addInitParameter("loginUsername", "admin"); bean.addInitParameter("loginPassword", "admin"); return bean; } } ``` #### 4️⃣ **排查与验证步骤** 如果问题仍然存在: 1. 检查依赖树: ```bash mvn dependency:tree | grep druid ``` 确保只存在 `druid-spring-boot-3-starter` 2. 清理 Maven 本地仓库: 删除 `~/.m2/repository/com/alibaba/druid` 目录后重新构建 3. 确认 Java 17 环境: ```bash java -version # 应显示17+ mvn -version # 需兼容JDK17 [^2] ``` 4. 检查依赖冲突(特别是连接池): ```xml <!-- 排除默认的 HikariCP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> <exclusions> <exclusion> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> </exclusion> </exclusions> </dependency> ``` #### 5️⃣ **常见错误原因** | 问题 | 解决方案 | |------|----------| | 使用旧版 Starter(如 `druid-spring-boot-starter`) | 替换为 `druid-spring-boot-3-starter` | | Druid 版本 < 1.2.8 | 升级到 ≥1.3.0 | | JDK 版本不匹配 | 确认使用 JDK 17+ [^2] | | 未声明数据源类型 | 添加 `spring.datasource.type` 配置 | | HikariCP 冲突 | 排除 `spring-boot-starter-jdbc` 中的 Hikari | > 💡 **最佳实践**:在 Spring Boot 3.x 中,始终使用 `druid-spring-boot-3-starter` 而非传统配置方式。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值