Spring Boot Native + Redis启动报错:无法创建RedisConnection Bean
问题:Spring Boot 3.1 Native应用Redis连接启动失败(Netty DNS解析NPE)
正在构建名为systemparam的Spring Boot 3.1 Native应用,采用Gradle构建、Lettuce作为Redis连接工厂、GraalVM CE Java17-22.3.2作为编译环境。应用通过标准编译可正常运行,但经Native编译后,启动时抛出UnsatisfiedDependencyException,提示无法创建cacheManager及redisConnection Bean,根源为Netty DNS解析相关的NullPointerException。已尝试添加io.lettuce:lettuce-core:6.2.4.RELEASE依赖,但问题未解决。
环境信息
named: systemparam. spring boot 3.1, gradle lettuce as connection factory graalvm-ce-java17-22.3.2
build.gradle配置
plugins { id 'java' id 'org.springframework.boot' version '3.1.0' id 'io.spring.dependency-management' version '1.1.0' id 'org.hibernate.orm' version '6.2.2.Final' id 'org.graalvm.buildtools.native' version '0.9.20' } group = 'id.pgd' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.projectreactor:reactor-test' testImplementation 'org.springframework.security:spring-security-test' } tasks.named('test') { useJUnitPlatform() } hibernate { enhancement { lazyInitialization true dirtyTracking true associationManagement true } }
启动报错信息
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cacheManager': Unsatisfied dependency expressed through method 'cacheManager' parameter 4: Error creating bean with name 'redisConnection': null at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:315) ~[na:na] at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:258) ~[na:na] at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:198) ~[na:na] at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:947) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1214) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:313) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[systemparam.exe:6.0.9] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1156) ~[systemparam.exe:6.0.9] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:931) ~[systemparam.exe:6.0.9] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[systemparam.exe:6.0.9] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[systemparam.exe:3.1.0] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733) ~[systemparam.exe:3.1.0] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435) ~[systemparam.exe:3.1.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[systemparam.exe:3.1.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1305) ~[systemparam.exe:3.1.0] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1294) ~[systemparam.exe:3.1.0] Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConnection': null at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:888) ~[na:na] at org.springframework.beans.factory.support.RegisteredBean.resolveAutowiredArgument(RegisteredBean.java:219) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:312) ~[na:na] 23 common frames omitted Caused by: java.lang.ExceptionInInitializerError: null at io.netty.resolver.dns.DnsServerAddressStreamProviders$DefaultProviderHolder$1.provider(DnsServerAddressStreamProviders.java:150) ~[na:na] at io.netty.resolver.dns.DnsServerAddressStreamProviders$DefaultProviderHolder$1.<init>(DnsServerAddressStreamProviders.java:130) ~[na:na] at io.netty.resolver.dns.DnsServerAddressStreamProviders$DefaultProviderHolder.<clinit>(DnsServerAddressStreamProviders.java:128) ~[na:na] at io.netty.resolver.dns.DnsServerAddressStreamProviders.unixDefault(DnsServerAddressStreamProviders.java:117) ~[na:na] at io.netty.resolver.dns.DnsServerAddressStreamProviders.platformDefault(DnsServerAddressStreamProviders.java:113) ~[na:na] at io.netty.resolver.dns.DnsNameResolverBuilder.<init>(DnsNameResolverBuilder.java:61) ~[na:na] at io.lettuce.core.resource.AddressResolverGroupProvider$DefaultDnsAddressResolverGroupWrapper.<clinit>(AddressResolverGroupProvider.java:56) ~[na:na] at io.lettuce.core.resource.AddressResolverGroupProvider.<clinit>(AddressResolverGroupProvider.java:35) ~[na:na] at io.lettuce.core.resource.DefaultClientResources.<clinit>(DefaultClientResources.java:112) ~[systemparam.exe:6.2.4.RELEASE] at io.lettuce.core.AbstractRedisClient.<init>(AbstractRedisClient.java:122) ~[systemparam.exe:6.2.4.RELEASE] at io.lettuce.core.RedisClient.<init>(RedisClient.java:99) ~[systemparam.exe:6.2.4.RELEASE] at io.lettuce.core.RedisClient.create(RedisClient.java:136) ~[systemparam.exe:6.2.4.RELEASE] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.lambda$createClient$7(LettuceConnectionFactory.java:1178) ~[systemparam.exe:3.1.0] at java.base@17.0.7/java.util.Optional.orElseGet(Optional.java:364) ~[systemparam.exe:na] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.createClient(LettuceConnectionFactory.java:1178) ~[systemparam.exe:3.1.0] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.afterPropertiesSet(LettuceConnectionFactory.java:324) ~[systemparam.exe:3.1.0] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1816) ~[systemparam.exe:6.0.9] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[systemparam.exe:6.0.9] 35 common frames omitted Caused by: java.lang.NullPointerException: null at java.base@17.0.7/sun.net.dns.ResolverConfigurationImpl.stringToList(ResolverConfigurationImpl.java:69) ~[na:na] at java.base@17.0.7/sun.net.dns.ResolverConfigurationImpl.loadConfig(ResolverConfigurationImpl.java:136) ~[na:na] at java.base@17.0.7/sun.net.dns.ResolverConfigurationImpl.nameservers(ResolverConfigurationImpl.java:159) ~[na:na] at jdk.naming.dns@17.0.7/com.sun.jndi.dns.DnsContextFactory.serversForUrls(DnsContextFactory.java:149) ~[systemparam.exe:na] at jdk.naming.dns@17.0.7/com.sun.jndi.dns.DnsContextFactory.getContext(DnsContextFactory.java:81) ~[systemparam.exe:na] at jdk.naming.dns@17.0.7/com.sun.jndi.dns.DnsContextFactory.urlToContext(DnsContextFactory.java:120) ~[systemparam.exe:na] at jdk.naming.dns@17.0.7/com.sun.jndi.dns.DnsContextFactory.getInitialContext(DnsContextFactory.java:64) ~[systemparam.exe:na] at java.naming@17.0.7/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:732) ~[systemparam.exe:na] at java.naming@17.0.7/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305) ~[systemparam.exe:na] at java.naming@17.0.7/javax.naming.InitialContext.init(InitialContext.java:236) ~[systemparam.exe:na] at java.naming@17.0.7/javax.naming.InitialContext.<init>(InitialContext.java:208) ~[systemparam.exe:na] at java.naming@17.0.7/javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:130) ~[systemparam.exe:na] at io.netty.resolver.dns.DirContextUtils.addNameServers(DirContextUtils.java:49) ~[na:na] at io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider.<clinit>(DefaultDnsServerAddressStreamProvider.java:55) ~[na:na] 53 common frames omitted
解决方案
自定义Lettuce客户端资源,规避DNS JNDI解析
创建Redis配置类,显式指定DNS解析方式,避免Netty自动加载系统DNS配置时触发NPE:@Configuration public class RedisConfig { @Bean public LettuceClientResources lettuceClientResources() { return DefaultClientResources.builder() .dnsAddressResolverGroup(DnsAddressResolverGroup.newBuilder() .nameResolver(DnsNameResolverBuilder.newInstance() .serverAddresses(DefaultDnsServerAddressStreamProvider.INSTANCE) .build()) .build()) .build(); } @Bean public LettuceConnectionFactory lettuceConnectionFactory(LettuceClientResources clientResources) { LettuceConnectionFactory factory = new LettuceConnectionFactory(); factory.setClientResources(clientResources); return factory; } }添加GraalVM编译参数,启用安全服务
在build.gradle中配置Native镜像构建参数,确保必要的系统服务可用:graalvmNative { binaries { main { buildArgs.add("--enable-all-security-services") } } }升级依赖版本
升级Spring Boot到3.1.5及以上,或Lettuce到6.2.6及以上,这些版本修复了Native环境下的DNS解析兼容性问题。直接使用Redis IP地址
将Redis配置中的域名替换为IP地址,彻底绕过DNS解析流程,消除NPE触发点。
内容的提问来源于stack exchange,提问作者Raey Juve
相关产品推荐
相关产品推荐

