无法在 HandlerInterceptorAdapter 中注入服务,获取 NullPointerException
Cannot Inject Service in HandlerInterceptorAdapter, Getting NullPointerException
我有一个服务客户端项目,它在正常的 spring 应用程序中,而不是 spring 启动。它主要用于与日志记录相关的 things.which 包含拦截器,loggingservice impl class 和一些用于日志记录的模型 classes。我已将此模块添加为 pom.xml
中主应用程序的依赖项。并且我能够在主应用程序的服务层中注入和使用 loggingService bean。
在拦截器中自动连接 loggingService 时得到 NullPointerException
。bean 在 interceptor.but 中不可用,就像我说的那样,它可以在主应用程序中注入和使用。
我也无法在拦截器中使用 @Value
读取属性。
这是我的拦截器 class .
@Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {
@Autowired
LoggingService loggingService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
loggingService.info("Am in prehandle");
return true;
}
}
这是我的配置class,我在主应用程序中注册了拦截器
@Component
public class LoggingConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getLoginInterceptor());
}
@Bean
public LoggingInterceptor getLoginInterceptor() {
return new LoggingInterceptor();
}
}
我的问题几乎与这个 post Cannot Autowire Service in HandlerInterceptorAdapter 相似,但它的不同之处在于我从另一个模块引用拦截器,就像他们建议的那样,我尝试从应用程序创建 bean。
但是现在面临的问题是
- 在拦截器中注入 loggingService 时得到
NullPointerException
,但它在主应用程序中工作
@Value
注释也 return 为 null,无法从属性中读取
您有 2 种可能的解决方案。
- 将您的
LoggingConfig
标记为 @Configuration
而不是 @Copmponent
- 注入
LoggingInterceptor
而不是引用 @Bean
方法
选项 1:LoggingConfig
作为 @Configuration
你的 LoggingConfig
被标记为 @Component
而它应该被标记为 @Configuration
。不同之处在于,虽然允许在 @Component
上使用 @Bean
方法,但它在所谓的 lite mode 中运行。这意味着您不能使用方法引用来获取 bean 的实例(这是因为没有创建特殊的代理)。这将导致只创建 LoggingInterceptor
的一个新实例,但它不是一个 bean。
所以简而言之,您所做的等同于 registry.addInterceptor(new LoggingInterceptor());
只是创建一个实例而 Spring 不知道它。
当将 LoggingConfig
标记为 @Configuration
时,将创建一个特殊的代理,这将使 LoggingInterceptor
成为一个合适的单例 bean,因为方法调用被拦截了。这将在 Spring 中注册 bean,您将能够调用该方法。
注意: 您实际上得到了 LoggingInterceptor
的 2 个实例,一个是由于 @Component
,另一个是 @Bean
.删除 @Component
。
选项 2:注入 LoggingInterceptor
。
因为您的 LoggingInterceptor
被标记为 @Component
Spring 将已经创建一个实例(您实际上在当前设置中创建了 2 个实例)。您可以将此实例注入您的 LoggingConfig
。
@Component
public class LoggingConfig implements WebMvcConfigurer {
private LoggingInterceptor loggingInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor);
}
}
有了这个,您可以删除 @Bean
方法,因为您将把正确的方法注入到您的 LoggingConfig
class 中。在这种情况下,class 也可以保留为 @Component
。虽然我建议使用 @Configuration
来正确地刻板印象。
注意: 如果您使用的是最新的 Spring 版本,您可以使用 @Configuration(proxyBeanMethods=false)
。这将生成精简配置(就像 @Component
),但它仍被正确标记为配置 class。
我有一个服务客户端项目,它在正常的 spring 应用程序中,而不是 spring 启动。它主要用于与日志记录相关的 things.which 包含拦截器,loggingservice impl class 和一些用于日志记录的模型 classes。我已将此模块添加为 pom.xml
中主应用程序的依赖项。并且我能够在主应用程序的服务层中注入和使用 loggingService bean。
在拦截器中自动连接 loggingService 时得到 NullPointerException
。bean 在 interceptor.but 中不可用,就像我说的那样,它可以在主应用程序中注入和使用。
我也无法在拦截器中使用 @Value
读取属性。
这是我的拦截器 class .
@Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {
@Autowired
LoggingService loggingService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
loggingService.info("Am in prehandle");
return true;
}
}
这是我的配置class,我在主应用程序中注册了拦截器
@Component
public class LoggingConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getLoginInterceptor());
}
@Bean
public LoggingInterceptor getLoginInterceptor() {
return new LoggingInterceptor();
}
}
我的问题几乎与这个 post Cannot Autowire Service in HandlerInterceptorAdapter 相似,但它的不同之处在于我从另一个模块引用拦截器,就像他们建议的那样,我尝试从应用程序创建 bean。 但是现在面临的问题是
- 在拦截器中注入 loggingService 时得到
NullPointerException
,但它在主应用程序中工作 @Value
注释也 return 为 null,无法从属性中读取
您有 2 种可能的解决方案。
- 将您的
LoggingConfig
标记为@Configuration
而不是@Copmponent
- 注入
LoggingInterceptor
而不是引用@Bean
方法
选项 1:LoggingConfig
作为 @Configuration
你的 LoggingConfig
被标记为 @Component
而它应该被标记为 @Configuration
。不同之处在于,虽然允许在 @Component
上使用 @Bean
方法,但它在所谓的 lite mode 中运行。这意味着您不能使用方法引用来获取 bean 的实例(这是因为没有创建特殊的代理)。这将导致只创建 LoggingInterceptor
的一个新实例,但它不是一个 bean。
所以简而言之,您所做的等同于 registry.addInterceptor(new LoggingInterceptor());
只是创建一个实例而 Spring 不知道它。
当将 LoggingConfig
标记为 @Configuration
时,将创建一个特殊的代理,这将使 LoggingInterceptor
成为一个合适的单例 bean,因为方法调用被拦截了。这将在 Spring 中注册 bean,您将能够调用该方法。
注意: 您实际上得到了 LoggingInterceptor
的 2 个实例,一个是由于 @Component
,另一个是 @Bean
.删除 @Component
。
选项 2:注入 LoggingInterceptor
。
因为您的 LoggingInterceptor
被标记为 @Component
Spring 将已经创建一个实例(您实际上在当前设置中创建了 2 个实例)。您可以将此实例注入您的 LoggingConfig
。
@Component
public class LoggingConfig implements WebMvcConfigurer {
private LoggingInterceptor loggingInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor);
}
}
有了这个,您可以删除 @Bean
方法,因为您将把正确的方法注入到您的 LoggingConfig
class 中。在这种情况下,class 也可以保留为 @Component
。虽然我建议使用 @Configuration
来正确地刻板印象。
注意: 如果您使用的是最新的 Spring 版本,您可以使用 @Configuration(proxyBeanMethods=false)
。这将生成精简配置(就像 @Component
),但它仍被正确标记为配置 class。