添加java-melody依赖后Spring Boot出现空指针异常,需补充哪些配置?
问题描述
在Spring Boot应用中添加java-melody starter依赖后,每次访问都会抛出空指针异常。
添加的POM依赖:
<dependency> <groupId>net.bull.javamelody</groupId> <artifactId>javamelody-spring-boot-starter</artifactId> <version>1.92.0</version> </dependency>
异常触发点与ValidationService相关,相关代码如下:
AuthenticationService核心代码
@Slf4j @Service public class AuthenticationService implements IAuthenticationService { @Autowired private ValidationService validationService; @Autowired private UserLoginDao userLoginDao; public TempLoginModel doSoftLogin(@Valid UserLoginRequest request) { UserLogin userLogin = userLoginDao.findByUsernameAndCorporateCode(request.getUsername()) .orElseThrow(() -> new UsernameNotFoundException( env.getProperty("message.authentication.service.wrong.credential"))); validationService.exceptionIfUserLoginNotActivated .andThen(validationService.exceptionIfUserLoginLocked) .accept(userLogin); String jwtToken = JWTUtil.createJwt(request.getUsername(), userLogin.getUserInformation().getMobileNumber()); return new TempLoginModel(jwtToken); } }
ValidationService核心代码
@Slf4j @Service public class ValidationService { public Consumer<UserLogin> exceptionIfUserLoginNotActivated = (user) -> { if (!user.isActivated()) { throw new NoAccessException(env.getProperty("message.user.login.not.activate")); } }; public Consumer<UserLogin> exceptionIfUserLoginLocked = (user) -> { if (user.getWrongLoginAttempt() >= getWrongPasswordAttemptCount()) { throw new NoAccessException(env.getProperty("message.user.login.locked")); } }; }
异常栈信息:
java.lang.NullPointerException: null at com.java.corporate.service.impl.AuthenticationService.exceptionIfInvalidLogin(AuthenticationService.java:355) at com.java.corporate.service.impl.AuthenticationService.doSoftLogin(AuthenticationService.java:190) at com.java.corporate.service.impl.AuthenticationService$$FastClassBySpringCGLIB$$1d9d9fd9.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at net.bull.javamelody.MonitoringSpringInterceptor.invoke(MonitoringSpringInterceptor.java:76) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
问题分析与解决方案
核心原因
- Spring AOP代理与成员变量冲突:JavaMelody通过Spring AOP生成CGLIB代理对象增强服务类时,不会自动代理类的public成员变量(如
ValidationService中的两个Consumer实例)。当AuthenticationService调用代理后的ValidationService的成员变量时,会拿到空引用,触发空指针。 - ValidationService依赖缺失:代码中
env(Environment)未注入,即使代理问题解决,env.getProperty()也会抛出空指针。
解决步骤
重构ValidationService,替换成员变量式Consumer
将Consumer改为普通方法,同时注入必要依赖:@Slf4j @Service public class ValidationService { @Autowired private Environment env; // 假设错误登录尝试次数配置在application.properties中 @Value("${security.wrong-login-attempt-count:5}") private int wrongLoginAttemptCount; public void validateUserLogin(UserLogin userLogin) { checkUserActivated(userLogin); checkUserLoginLocked(userLogin); } private void checkUserActivated(UserLogin user) { if (!user.isActivated()) { throw new NoAccessException(env.getProperty("message.user.login.not.activate")); } } private void checkUserLoginLocked(UserLogin user) { if (user.getWrongLoginAttempt() >= wrongLoginAttemptCount) { throw new NoAccessException(env.getProperty("message.user.login.locked")); } } }修改AuthenticationService的调用逻辑
替换原有的Consumer链式调用为普通方法调用:// 替换原来的Consumer调用代码 validationService.validateUserLogin(userLogin);JavaMelody的可选配置
基础场景下starter默认配置即可运行,若需要自定义监控规则,可在application.properties中添加:# 排除静态资源或无需监控的接口 javamelody.excluded-urls=/css/**,/js/**,/health/** # 排除特定包下的类不被监控 javamelody.excluded-packages=com.java.corporate.util # 开启监控页面的登录验证(可选) javamelody.authorized-users=admin:admin123若遇到AOP代理冲突,可强制使用CGLIB代理:
spring.aop.proxy-target-class=true
内容的提问来源于stack exchange,提问作者Sudan Shrestha
相关产品推荐
相关产品推荐

