作者:hinotoyk
链接:https://juejin.cn/post/6910215219822362632
背景:某日在公司中撸代码的时候,在一个常用的controller中添加一个方法,测试时突然报错说注入的service为null,捣鼓一阵发现后是方法修饰符写成private,修改成public后搞定。为什么会产生这个问题呢?就自己测试一下是哪里发生了问题
首先简单模拟一下环境
Spring Boot 基础就不介绍了,推荐看这个实战项目:
https://github.com/javastacks/spring-boot-best-practice
public interface TestService {
String getTestString();
}
@Service("testService")
public class TestServiceImpl implements TestService {
@Override
public String getTestString() {
return "hinotoyk";
}
}
@RestController
public class MainController {
@Autowired
private TestService service;
@RequestMapping("/testA")
public String testA(){
return service.getTestString();
}
@RequestMapping("/testB")
private String testB(){
return service.getTestString();
}
}
/testA是pulibc,/testB是pirvate,测试结果均能返回"hinotoyk"字符串
测试和公司环境还有一个不太同的就是公司项目中有Aop切面处理访问日志的,还要添加一个Aop
@Aspect
@Component
public class WebLogAspect {
private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
@Pointcut("execution(public * com.spring.controller..*.*(..))")
public void controllerLog(){}
@Before("controllerLog()")
public void logBeforeController(JoinPoint joinPoint) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
logger.info("*************URL : " + request.getRequestURL().toString());
logger.info("*************HTTP_METHOD : " + request.getMethod());
logger.info("*************IP : " + request.getRemoteAddr());
}
}
添加了一个 Aop 后测试:
/testA返回"hinotoyk"字符串
/testB访问报错,service注入失败,为null
为什么使用Aop会导致private修饰的方法注入失败,查询了许多资料后发现一位老哥的SpringAOP导致@Autowired依赖注入失败中说到org.springframework.aop.support.AopUtils中的代码使用的是Method[] methods = clazz.getMethods(),即是只能拿到public方法。但是我使用的版本2.1.4.RELEASE中已经使用Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);这就有点迷惑了
会不会是切点注解中的修饰符匹配不到呢?将切点中的修饰符从public修改成private
@Pointcut("execution(private* com.spring.controller..*.*(..))")
public void controllerLog(){}
测试结果:
/testA返回"hinotoyk"字符串
/testB访问报错,service注入失败,为null
还是不行(就挺秃然的)
目前结论
- 方法中没有用@Autowired或者@Resource注入的对象。有无Aop,任意修饰符都可以正常访问并且返回结果
- 方法中使用了@Autowired或者@Resource注入的对象
没有Aop切面的情况下,public,protected,private都能正常的映射
在有Aop切面的情况下,public,protected可以正常映射,但是使用private会报空指针异常,注入对象为null
近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2022最新版)
2.劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!
5.《Java开发手册(嵩山版)》最新发布,速速下载!
觉得不错,别忘了随手点赞+转发哦!