背景 最近,在公司CodeReview会上,我给众多同事布置了家庭作业。Controller中的请求方法,通常我们都是public的,如果是private的、protected的行不行,为什么? 后来一个同事比较认真,第二天早上测试后发现报错了,给我反馈说private方法的内部注入的service为null,修改成public后就不会为null。为什么会产生这个问题呢?这个同事没有回答出来,今天我抽空调试了一下源码,给大家总结一下,分享给大家!首先简单模拟一下环境publicinterfaceTestService{StringgetTestString();}Service(testService)publicclassTestServiceImplimplementsTestService{OverridepublicStringgetTestString(){return业余草;}}RestControllerpublicclassMainController{AutowiredprivateTestSRequestMapping(testA)publicStringtestA(){returnservice。getTestString();}RequestMapping(testB)privateStringtestB(){returnservice。getTestString();}} testA是pulibc,testB是pirvate,测试结果均能返回业余草字符串 测试和公司环境还有一个不太同的就是公司项目中有Aop切面处理访问日志的,还要添加一个Aop。AspectComponentpublicclassWebLogAspect{privatefinalLoggerloggerLoggerFactory。getLogger(WebLogAspect。class);Pointcut(execution(publiccom。spring。controller。。。(。。)))publicvoidcontrollerLog(){}Before(controllerLog())publicvoidlogBeforeController(JoinPointjoinPoint){RequestAttributesrequestAttributesRequestContextHolder。getRequestAttributes();HttpServletRequestrequest((ServletRequestAttributes)requestAttributes)。getRequest();logger。info(URL:request。getRequestURL()。toString());logger。info(HTTPMETHOD:request。getMethod());logger。info(IP:request。getRemoteAddr());}} 添加了一个Aop后测试:testA返回业余草字符串testB访问报错,service注入失败,为null 为什么使用Aop会导致private修饰的方法注入失败,查询了许多资料,网上有人说到org。springframework。aop。support。AopUtils中的代码使用的是Method〔〕methodsclazz。getMethods(),即是只能拿到public方法。但是我使用的版本2。1。4。RELEASE中已经使用Method〔〕methodsReflectionUtils。getAllDeclaredMethods(clazz);这就有点迷惑了。 会不会是切点注解中的修饰符匹配不到呢?将切点中的修饰符从public修改成private。Pointcut(execution(privatecom。spring。controller。。。(。。)))publicvoidcontrollerLog(){} 测试结果:testA返回业余草字符串testB访问报错,service注入失败,为null 还是不行(就挺秃然的)。 哎,想偷懒还不行,只能我一行一行调试代码了。目前结论方法中没有用Autowired或者Resource注入的对象。有无Aop,任意修饰符都可以正常访问并且返回结果方法中使用了Autowired或者Resource注入的对象 没有Aop切面的情况下,public,protected,private都能正常的映射 在有Aop切面的情况下,public,protected可以正常映射,但是使用private会报空指针异常,注入对象为null。 最后经过我的一番折腾与调试之后,发现: 使用了aop,也就是使用动态代理,你的SpringBoot版本为2。1。4release,底层默认调用的是cglib作为动态代理。 其本质是:调用某个类的方法时,实际上是先为该类生成一个子类,然后再在子类中通过反射等,达到方法拦截的目的。对于子类,其父类中,private修饰的方法,子类如果与父类不在同一包下,是没有访问的权限的,此场景下,cglib生成的子类,不会和父类在同一包下,也就是private修饰的方法,不能进行动态代理,所以会报空指针异常。