为什么在这个春季的应用程序中,自动装配的bean在过滤器中为空? [英] why is autowired bean null in filter in this spring application?
问题描述
我简化了生产应用程序以重现错误.
I have simplified our production application to reproduce the errors.
这是一个演示应用程序,用于计算传入请求的数量.
This is a demo application to calculate the counts of incoming requests.
当我调试项目时,我看到Null Pointer Exception
被抛出
CounterMetricsFilter
类中的manager.incrementRequestCounter(url)
行如下所示.那是因为我拥有autowired
的经理是NULL.
when I debugged the project, I can see Null Pointer Exception
being thrown at
manager.incrementRequestCounter(url)
line in CounterMetricsFilter
class shown below. That is because manager I have autowired
is NULL.
但是,CounterController
中的同一管理器autowired
不为空.我通过调试器确认了这一点.
However, the same manager autowired
in CounterController
is NOT null. I confirmed this through debugger.
这是怎么了? filters
不能是beans
吗?如何在不使用Spring MVC
应用程序中使用web.xml
的情况下实现此功能.
what is wrong here? can filters
not be beans
? how can I get to this to work without using web.xml
in Spring MVC
application.
谢谢
Controller
@Controller
@RequestMapping("/counter")
public class CounterController {
@Autowired
CounterManager manager;
@RequestMapping(value = "/counterMetrics", method = RequestMethod.GET)
@ResponseBody
public Map getFeatureStatus(final HttpServletResponse response) {
System.out.println("returning feautre status");
return manager.getQueryCounts();
}
}
Manager
@Service
public class CounterManager {
private Map<String,Integer> queryCounts =
new ConcurrentHashMap<String,Integer>(1000);
int threshold;
long timestamp;
@Autowired
public CounterManager(@Value("${healthThreshold: 10}")
int threshold) {
this.threshold = threshold * MEGABYTES;
this.timestamp = System.currentTimeMillis();
}
public void incrementRequestCounter(String urlPath){
Integer oldVal, newVal;
do {
oldVal = queryCounts.get(model);
newVal = (oldVal == null) ? 1 : (oldVal + 1);
} while (!queryCounts.replace(model, oldVal, newVal));
}
public Map<StatusUrlModel, Integer> getQueryCounts() {
return queryCounts;
}
}
Filter
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class CounterMetricsFilter extends OncePerRequestFilter {
@Autowired
CounterManager manager;
public CounterMetricsFilter(){
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) throws ServletException,
IOException {
String path = new UrlPathHelper().getPathWithinApplication(request);
try {
chain.doFilter(request, response);
}
finally {
recordMetrics(request, path);
}
}
private void recordMetrics(String path) {
try {
manager.incrementRequestCounter(url);
}
catch (Exception ex){
System.out.println("exception is thrown " + ex.getCause());
ex.printStackTrace();
}
}
}
更新:
在控制台上打印以下内容:
The get the following printed on console:
exception is thrown null
(来自上面的CounterMetricsFilter).
stackTrace:
exception is thrown null
(coming from CounterMetricsFilter above).
stackTrace:
java.lang.NullPointerException
at com.myapp.filter.CounterMetricsFilter.recordMetrics(CounterMetricsFilter.java:81)
at com.myapp.filter.CounterMetricsFilter.doFilterInternal(CounterMetricsFilter.java:63)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.myapp.filter.RequestWrapperFilter.doFilter(RequestWrapperFilter.java:24)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.myapp.filter.GCCORSFilter.doFilter(GCCORSFilter.java:37)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
推荐答案
Servlet容器实例化了一个过滤器,因此@Autowired
没有用.
A filter is instantiated by the servlet container so @Autowired
is useless.
您可以使用DelegatingFilterProxy
让Spring实例化过滤器:
You can use a DelegatingFilterProxy
to let Spring instantiate the filter:
<filter>
<filter-name>counterMetricsFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
这篇关于为什么在这个春季的应用程序中,自动装配的bean在过滤器中为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!