首次使用拦截器遇Null Pointer Exception,求原因分析(已用Qualifier)
Hey there! Let's break down why you might be hitting that Null Pointer Exception (NPE) while building your logging interceptor with the @Qualifier annotation. Since you mentioned following A. Goncalves' course, let's walk through the most common pitfalls when setting up interceptors and custom qualifiers in Java frameworks (I'll cover both Spring and CDI, since those are the most common for this use case):
1. Your Interceptor Dependencies Aren't Properly Injected
If your logging interceptor relies on a dependency (like a Logger instance or another service) that isn't being injected by the framework, accessing that dependency will throw an NPE. For example:
public class LoggingInterceptor { // Oops! No @Autowired/@Inject here means this stays null private Logger logger; @AroundInvoke public Object logMethodCall(InvocationContext ctx) throws Exception { logger.info("Calling method: " + ctx.getMethod().getName()); // NPE triggers here return ctx.proceed(); } }
Fix: Use @Autowired (Spring) or @Inject (CDI) to mark dependencies for injection, and ensure the dependency class is managed by your framework's container.
2. Mismatched @Qualifier Annotations
Your custom qualifier annotation might not be properly paired with the interceptor bean. If you're using the qualifier to inject the interceptor, but the interceptor class itself doesn't carry the same qualifier, the container won't find a matching bean and will inject null. Example:
// Your custom qualifier (partial code you provided) @Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD}) public @interface LoggingInterceptorQualifier {} // Interceptor class missing the qualifier public class LoggingInterceptor implements Interceptor { ... } // Injection point using the qualifier (no matching bean found) @Inject @LoggingInterceptorQualifier private Interceptor loggingInterceptor; // NPE here
Fix: Add your custom qualifier annotation directly to the interceptor class, or double-check that the qualifier used at the injection point exactly matches the one on the bean.
3. The Interceptor Isn't Registered with the Framework
Most frameworks require explicit registration of interceptors—if you skip this step, the container won't manage the interceptor, and any attempts to inject it will result in null.
- For Spring: Register it in a configuration class:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // Either create a new instance or inject the managed bean registry.addInterceptor(new LoggingInterceptor()); } } - For CDI: Ensure the interceptor has the
@Interceptorannotation, and enable it viabeans.xmlor the@Priorityannotation.
4. Null Checks Missing for InvocationContext Values
When working with InvocationContext methods like getMethod() or getTarget(), these can return null in certain scenarios (e.g., intercepting a constructor call). If you use these values without checking for null first, you'll hit an NPE:
public Object logMethodCall(InvocationContext ctx) throws Exception { // getMethod() might return null here logger.info("Calling method: " + ctx.getMethod().getName()); return ctx.proceed(); }
Fix: Add null checks before accessing values from InvocationContext:
Method targetMethod = ctx.getMethod(); if (targetMethod != null) { logger.info("Calling method: " + targetMethod.getName()); }
5. Incomplete Custom Qualifier Definition
From the partial code you shared, make sure your custom qualifier includes all required elements:
- It must be annotated with
@Qualifier(the framework's qualifier meta-annotation) @Retention(RUNTIME)is required so the framework can read it at runtime@Targetshould includeFIELDif you plan to use the qualifier for field injection
Here's the complete, correct definition:
package classes; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.FIELD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.inject.Qualifier; // Use org.springframework.beans.factory.annotation.Qualifier for Spring @Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD}) public @interface YourQualifierName {}
If you can share a bit more code—like the full interceptor class, where you're injecting it, and any framework configuration—it'll be easier to pinpoint the exact issue!
内容的提问来源于stack exchange,提问作者ziMtyth

