在 Spring 中创建 bean 期间发生 NullPointerException
NullPointerException during bean creation in Spring
我在带有注释 @Bean
的方法中收到 NullPointerException,但在此之前我从未在那里收到此 NullPointerException:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [dev.teamnight.command.CommandFramework]: Circular reference involving containing bean 'config' - consider declaring the factory method as static for independence from its containing instance. Factory method 'commandFramework' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
... 68 common frames omitted
Caused by: java.lang.NullPointerException: null
at dev.teamnight.nightbot.Config.commandFramework(Config.java:84) ~[classes/:na]
at dev.teamnight.nightbot.Config$$EnhancerBySpringCGLIB$d4937ec.CGLIB$commandFramework(<generated>) ~[classes/:na]
at dev.teamnight.nightbot.Config$$EnhancerBySpringCGLIB$d4937ec$$FastClassBySpringCGLIB$fbdfefd.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at dev.teamnight.nightbot.Config$$EnhancerBySpringCGLIB$d4937ec.commandFramework(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
... 69 common frames omitted
导致异常的文件代码:
@Configuration
@PropertySource("file:bot.properties")
public class Config {
@Autowired
private ShardManager shardManager;
@Autowired
private PermissionProvider permissionProvider;
@Autowired
private LanguageProvider languageProvider;
@Autowired
private PrefixProvider prefixProvider;
@Autowired
private HelpProvider helpProvider;
@Bean
public ShardManager shardManager() throws LoginException, IllegalArgumentException {
DefaultShardManagerBuilder builder = DefaultShardManagerBuilder.createDefault(this.botToken)
.enableIntents(GatewayIntent.GUILD_MEMBERS)
.setMemberCachePolicy(MemberCachePolicy.ALL)
.setStatus(OnlineStatus.IDLE)
.setShardsTotal(this.totalShards)
.addEventListeners(Arrays.asList(this.jdaListener()));
return builder.build();
}
@Bean
public CommandFramework commandFramework() {
Logger log = LogManager.getLogger();
//Line causing the error below!
log.error("Name of helpProvider: " + this.helpProvider.getClass().getCanonicalName());
return new FrameworkBuilder()
.addOwners(Arrays.stream(this.ownerIds).filter(ownerId -> ownerId.matches("^(\d)+$")).map(ownerId -> Long.parseLong(ownerId)).collect(Collectors.toList()))
.setLogger(NightBot.logger())
.allowBots(false)
.allowDM(false)
.allowMention(true)
.allowRainbowColors(true)
.withPrefixProvider(this.prefixProvider)
.withLanguageProvider(this.languageProvider)
.withPermissionProvider(this.permissionProvider)
.withHelpProvider(this.helpProvider)
.withCustomArgumentProcessor(new NamedArgumentProcessor())
.registerClient(this.shardManager)
.build();
}
}
正如我所说,在代码完全运行之前,我对 Config.java 文件没有任何更改,所以这个错误让我很困惑。
你看到这个 NullPointerException
因为自动装配 HelperProvider
没有被注入。
您正试图在空对象上调用 .getClass()
。
一般依赖注入调试
只想添加一个快速的基本提及,因为这个问题的主要答案必须对您的代码库做出一些假设。当依赖注入失败时,您需要检查几件事情。
- 配置文件 - 是否正确加载了这些文件。您的组件扫描最近是否被禁用?
- 您的
Components
有必要的 @Component
和/或 @Service/@Controller/@Repository
注释吗?
可能的根本问题 - 循环引用 - BeanInstantiationException
您的堆栈跟踪中还提到了循环引用,这很可能是导致问题的原因。
Caused by: org.springframework.beans.BeanInstantiationException: Circular reference involving containing bean 'config' - consider declaring the factory method as static for independence from its containing instance. Factory method 'commandFramework' threw exception; nested exception is java.lang.NullPointerException
自从您收到此错误消息后,您引入了循环引用。这意味着......一个组件依赖于一个依赖于该组件的组件。
例如:
@Component
class HelperProvider {
@Autowired
Config config;
}
和
@Configuration
class Config {
@Autowired
HelperProvider helperProvider
}
此模式将阻碍 spring 框架,因为它们相互依赖以加载每个组件。如果您进一步引入依赖项,就会发生这种情况。说 HelperProvider 需要 HelperHelperProvider 需要 Config.
您需要在最近的编辑中检查 Config
或 CommandFramework
的任何新注入。
你应该做什么
您需要重新设计您的配置以打破它对 HelperProvider
的依赖。这样做可以解决你以后很多头疼的问题。
你不应该做的事情
可以使用 @Lazy
注释延迟加载组件或配置。这样,bean 仅在调用时实例化。如果你想在启动时了解更多细微差别,推荐 Spring ApplicationContext
,但维护起来将成为一场噩梦。
您遇到的错误很可能是因为您的项目中存在循环依赖。并且由于您在 commandFramework 方法中获取它,如错误所示,这是因为您在其中再次使用 Config class 的 HelpProvider class。
因此,当 spring 创建 Config 的 bean 时,它必须创建一个 HelpProvider 的 bean,换句话说,它想要创建一个 Config 的 bean(在 HelpProvider 中自动装配)并导致一个永无止境的循环,给出错误。还要检查 HelpProvider 是否有 @component 注释。
配置 -> HelpProvider -> 配置 -> HelpProvider -> 配置 ...............
解决方法:-
- 或者您可以从 HelpProvider 中删除配置并尝试重新设计它。
- 在 HelpProvider 的 Config 上使用 @Lazy,这将加载对对象实例化的依赖。将建议它作为最后的手段。
我在带有注释 @Bean
的方法中收到 NullPointerException,但在此之前我从未在那里收到此 NullPointerException:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [dev.teamnight.command.CommandFramework]: Circular reference involving containing bean 'config' - consider declaring the factory method as static for independence from its containing instance. Factory method 'commandFramework' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
... 68 common frames omitted
Caused by: java.lang.NullPointerException: null
at dev.teamnight.nightbot.Config.commandFramework(Config.java:84) ~[classes/:na]
at dev.teamnight.nightbot.Config$$EnhancerBySpringCGLIB$d4937ec.CGLIB$commandFramework(<generated>) ~[classes/:na]
at dev.teamnight.nightbot.Config$$EnhancerBySpringCGLIB$d4937ec$$FastClassBySpringCGLIB$fbdfefd.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[spring-context-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at dev.teamnight.nightbot.Config$$EnhancerBySpringCGLIB$d4937ec.commandFramework(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
... 69 common frames omitted
导致异常的文件代码:
@Configuration
@PropertySource("file:bot.properties")
public class Config {
@Autowired
private ShardManager shardManager;
@Autowired
private PermissionProvider permissionProvider;
@Autowired
private LanguageProvider languageProvider;
@Autowired
private PrefixProvider prefixProvider;
@Autowired
private HelpProvider helpProvider;
@Bean
public ShardManager shardManager() throws LoginException, IllegalArgumentException {
DefaultShardManagerBuilder builder = DefaultShardManagerBuilder.createDefault(this.botToken)
.enableIntents(GatewayIntent.GUILD_MEMBERS)
.setMemberCachePolicy(MemberCachePolicy.ALL)
.setStatus(OnlineStatus.IDLE)
.setShardsTotal(this.totalShards)
.addEventListeners(Arrays.asList(this.jdaListener()));
return builder.build();
}
@Bean
public CommandFramework commandFramework() {
Logger log = LogManager.getLogger();
//Line causing the error below!
log.error("Name of helpProvider: " + this.helpProvider.getClass().getCanonicalName());
return new FrameworkBuilder()
.addOwners(Arrays.stream(this.ownerIds).filter(ownerId -> ownerId.matches("^(\d)+$")).map(ownerId -> Long.parseLong(ownerId)).collect(Collectors.toList()))
.setLogger(NightBot.logger())
.allowBots(false)
.allowDM(false)
.allowMention(true)
.allowRainbowColors(true)
.withPrefixProvider(this.prefixProvider)
.withLanguageProvider(this.languageProvider)
.withPermissionProvider(this.permissionProvider)
.withHelpProvider(this.helpProvider)
.withCustomArgumentProcessor(new NamedArgumentProcessor())
.registerClient(this.shardManager)
.build();
}
}
正如我所说,在代码完全运行之前,我对 Config.java 文件没有任何更改,所以这个错误让我很困惑。
你看到这个 NullPointerException
因为自动装配 HelperProvider
没有被注入。
您正试图在空对象上调用 .getClass()
。
一般依赖注入调试
只想添加一个快速的基本提及,因为这个问题的主要答案必须对您的代码库做出一些假设。当依赖注入失败时,您需要检查几件事情。
- 配置文件 - 是否正确加载了这些文件。您的组件扫描最近是否被禁用?
- 您的
Components
有必要的@Component
和/或@Service/@Controller/@Repository
注释吗?
可能的根本问题 - 循环引用 - BeanInstantiationException
您的堆栈跟踪中还提到了循环引用,这很可能是导致问题的原因。
Caused by: org.springframework.beans.BeanInstantiationException: Circular reference involving containing bean 'config' - consider declaring the factory method as static for independence from its containing instance. Factory method 'commandFramework' threw exception; nested exception is java.lang.NullPointerException
自从您收到此错误消息后,您引入了循环引用。这意味着......一个组件依赖于一个依赖于该组件的组件。
例如:
@Component
class HelperProvider {
@Autowired
Config config;
}
和
@Configuration
class Config {
@Autowired
HelperProvider helperProvider
}
此模式将阻碍 spring 框架,因为它们相互依赖以加载每个组件。如果您进一步引入依赖项,就会发生这种情况。说 HelperProvider 需要 HelperHelperProvider 需要 Config.
您需要在最近的编辑中检查 Config
或 CommandFramework
的任何新注入。
你应该做什么
您需要重新设计您的配置以打破它对 HelperProvider
的依赖。这样做可以解决你以后很多头疼的问题。
你不应该做的事情
可以使用 @Lazy
注释延迟加载组件或配置。这样,bean 仅在调用时实例化。如果你想在启动时了解更多细微差别,推荐 Spring ApplicationContext
,但维护起来将成为一场噩梦。
您遇到的错误很可能是因为您的项目中存在循环依赖。并且由于您在 commandFramework 方法中获取它,如错误所示,这是因为您在其中再次使用 Config class 的 HelpProvider class。
因此,当 spring 创建 Config 的 bean 时,它必须创建一个 HelpProvider 的 bean,换句话说,它想要创建一个 Config 的 bean(在 HelpProvider 中自动装配)并导致一个永无止境的循环,给出错误。还要检查 HelpProvider 是否有 @component 注释。
配置 -> HelpProvider -> 配置 -> HelpProvider -> 配置 ...............
解决方法:-
- 或者您可以从 HelpProvider 中删除配置并尝试重新设计它。
- 在 HelpProvider 的 Config 上使用 @Lazy,这将加载对对象实例化的依赖。将建议它作为最后的手段。