Redian新闻
>
Controller中的请求方法,private和public有什么区别?

Controller中的请求方法,private和public有什么区别?

公众号新闻

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 
来源:juejin.cn/post/
6910215219822362632

背景

最近,在公司 CodeReview 会上,我给众多同事布置了“家庭作业”。Controller 中的请求方法,通常我们都是 public 的,如果是 private 的、protected 的行不行,为什么?


后来一个同事比较认真,第二天早上测试后发现报错了,给我反馈说 private 方法的内部注入的 service 为 null,修改成 public 后就不会为 null。为什么会产生这个问题呢?这个同事没有回答出来,今天我抽空调试了一下源码,给大家总结一下,分享给大家!

首先简单模拟一下环境

public interface TestService {
    String getTestString();
}

@Service("testService")
public class TestServiceImpl implements TestService {
    @Override
    public String getTestString() {
        return "业余草";
    }
}
    
@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,测试结果「均能返回"业余草"字符串」

测试和公司环境还有一个不太同的就是公司项目中有 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返回"业余草"字符串  
/testB访问报错,service注入失败,为null

为什么使用 Aop 会导致 private 修饰的方法注入失败,查询了许多资料,网上有人说到 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返回"业余草"字符串  
/testB访问报错,service注入失败,为null

还是不行(就挺秃然的)。

哎,想偷懒还不行,只能我一行一行调试代码了。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

目前结论

  1. 方法中没有用@Autowired或者@Resource注入的对象。有无 Aop,任意修饰符都可以正常访问并且返回结果
  2. 方法中使用了@Autowired或者@Resource注入的对象 没有 Aop 切面的情况下,publicprotectedprivate都能正常的映射 在有 Aop 切面的情况下,publicprotected可以正常映射,但是使用private会报空指针异常,注入对象为 null。

最后经过我的一番折腾与调试之后,发现:

使用了 aop,也就是使用动态代理,你的 SpringBoot 版本为 2.1.4 release,底层默认调用的是 cglib 作为动态代理。

其本质是:调用某个类的方法时,实际上是先为该类生成一个子类,然后再在子类中通过反射等,达到方法拦截的目的。对于子类,其父类中,private修饰的方法,子类如果与父类不在同一包下,是没有访问的权限的,此场景下,cglib 生成的子类,不会和父类在同一包下,也就是private修饰的方法,不能进行动态代理,所以会报空指针异常。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
粗粮—细粮Playstation 4 Pro 1TB with 1 controllerPlaystion 4 Slim 500gb with one controller (system 7.02)#英语学习#IN, ON和AT有什么区别?慈济厨房的老师们Playstation 4 Pro 1TB with 1 black controller怕冷的人和抗冻的人,体质上究竟有什么区别?[腕表] JAEGER-LECOULTRE Master Control女人的四季,春夏秋冬Rosalía 登意大利版《VOGUE》封面!#英语学习#Afflict和Inflict有什么区别?看看你能答对这道题吗?同样是痔疮,内痔和外痔有什么区别?哪个更严重?China Strengthens Cyber Violence Policing After Teacher’s Death鼻窦炎和感冒有什么区别?专家建议:有这2个表现,80%是鼻窦炎恭喜Boston College学员斩获BlackRock(US)2023 Internship Offer!上浆、挂糊和勾芡有什么区别?用对了方法菜更好吃!刷脸支付与指纹支付有什么区别?是否安全?一文看懂!心理医生的诊断能全信吗?买房风波(全文完)Soy Sauce ‘Double Standards’ Stir Massive Controversy in China冥想、禅定、打坐到底有什么区别?丨冥想Q&A都是一贯制私立国际学校,他们之间有什么区别?抢光县城退烧药的城里人,他们杀人犯有什么区别?!#英语学习#Farther和Further有什么区别?看看你能答对这道题吗?同样是PM,Product Manager、Program Manager、Project Manager的薪资哪个更高?同居前的亲密行为 VS 同居后的亲密行为,有什么区别?空调制热和制冷 26 度,有什么区别?美国EB1A和NIW有什么区别?我就和你较真一次Linux 中的 su 和 sudo 命令有什么区别? | Linux 中国住ICU意味着什么?这的病人都没救了?ICU与普通病房有什么区别?《神奇校车》的版本这么多,有什么区别?按什么顺序读?生物、化学、生化,这三个专业有什么区别?[语法] fit 和 suit 都是“适合”,有什么区别?网络协议:TCP和UDP什么区别?(附视频)After a Blistering Summer, China Braces for a Frigid Winter
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。