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

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


背景

最近,在公司 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 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

目前结论

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

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

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

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

image.png

相关文章
|
21天前
|
人工智能 安全 IDE
公司不给你配 AI,你会自己掏钱吗?
AI正成为新时代的“办公软件”,开发者每月自费数百元订阅Claude、Cursor、Copilot等工具,实为工作刚需。公司尚未建立报销机制,但先行投入者已悄然积累不可替代的AI能力——这并非倒贴,而是抢占效率高地的聪明投资。
147 0
公司不给你配 AI,你会自己掏钱吗?
|
2月前
|
人工智能 并行计算 数据挖掘
视频配音翻译多角色识别Speaker Diarization 工程实践与踩坑记录
视频配音翻译多角色识别Speaker Diarization 工程实践与踩坑记录
|
10月前
|
人工智能 数据可视化 物联网
RFID在生产治具管理中发挥重要作用
RFID技术实现治具全生命周期数字化管理,涵盖入库、领用、定位、维护、盘点与追溯六大环节,提升管理效率90%以上,降低丢失率80%,助力智能制造升级。
|
7月前
|
人工智能 搜索推荐 安全
2026年LLM Agent对比传统Agent优势有哪些
2026年,AI正经历从“工具”到“伙伴”的范式革命。传统Agent受限于僵化流程,而LLM Agent以大模型为“大脑”,具备规划、记忆与工具调用能力,实现从执行到思考的跨越。适应复杂任务、动态决策与多智能体协作,推动AI迈向可信生产力。企业需拥抱认知驱动的智能体系统,构建人机协同的未来工作流。
929 0
|
9月前
|
存储 数据可视化 物联网
RFID让工具管理的不再难
RFID技术赋能工具管理,实现采购、领用、维护到报废的全生命周期数字化管控。广泛应用于工业制造、医疗、物流等领域,解决找工具难、盘点耗时、丢失率高等痛点,提升效率50%以上,助力企业降本增效,推动数字化转型。(238字)
|
数据采集 JSON 数据可视化
高德地图百度腾讯谷歌采集工具,可提取名称 地址 电话 手机号,精准autojs版下载
这是一款基于Auto.js开发的地图商家信息采集工具,支持高德、百度、腾讯和谷歌四大地图平台的数据抓取。可提取商家名称、地址、电话等关键信息
|
存储 人工智能 前端开发
【AI系统】LLVM IR 基本概念
本文深入探讨了LLVM的IR(中间表示)概念,解释了其在编译器工作原理中的重要性及应用方式。LLVM IR作为一种适中抽象级别的表示形式,能有效捕捉源代码信息,支持编译器的灵活操作与优化。文章进一步分析了LLVM IR的不同表现形式,包括内存中的编译中间语言、硬盘上的二进制格式和人类可读的文本格式,以及通过具体示例展示了如何使用Clang将C语言程序编译为LLVM IR。此外,还详细解析了LLVM IR的基本语法、条件语句、循环结构和指针操作等内容。
709 3
|
人工智能 程序员 Python
用通义灵码创建脚本
用通义灵码创建脚本
|
存储 JSON 前端开发
为什么String跟JSON不是同个东西?
很多人会误解JSON仅仅是序列化后的String,但这样的表述并不完全准确。JSON本质上是以字符串(String)形式表示的数据交换格式,但它不仅仅是一个字符串,而是具有特定语法和结构的字符串。 很经常遇到的一个场景: 后端:我给你返回了一段JSON,你转化下再遍历吧。
|
人工智能 API 语音技术
[AI MoneyPrinterTurbo] 一键成片,超级印钞机
探索MoneyPrinterTurbo的奇妙旅程,一个文生视频工具,让您只需一键,就能体验从安装到配置,再到创建高清短视频的全过程。
[AI MoneyPrinterTurbo] 一键成片,超级印钞机

热门文章

最新文章