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

相关文章
|
前端开发 Java 网络架构
ContentNegotiation内容协商机制(三)---在视图View上的应用:ContentNegotiatingViewResolver深度解析【享学Spring MVC】(上)
ContentNegotiation内容协商机制(三)---在视图View上的应用:ContentNegotiatingViewResolver深度解析【享学Spring MVC】(上)
ContentNegotiation内容协商机制(三)---在视图View上的应用:ContentNegotiatingViewResolver深度解析【享学Spring MVC】(上)
|
存储 SQL 关系型数据库
|
6天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1914 6
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
4天前
|
存储 人工智能 关系型数据库
阿里云AI产品与云产品最新组合套餐:Token Plan、AI coding及云服务器和建站等组合优惠价
阿里云推出全新“算力+模型+应用”一站式云与AI组合套餐活动,覆盖从个人开发者到中大型企业的全场景需求。核心亮点为分三档定价的Token Plan订阅服务,支持Qwen3.8-Max-Preview大模型调用,错峰时段最低可享0.2折优惠。活动同步推出AI Coding、智能体部署、云电脑托管、0代码建站等十余类场景化组合,搭配99元/年的普惠云服务器、88元/年的入门数据库等经典特惠产品,还为企业提供1V1定制化AI转型方案,大幅降低了不同用户群体拥抱AI的技术门槛与采购成本。
643 110
|
14天前
|
人工智能 JSON 安全
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
阿里云AI安全产品联动防御Fastjson攻击
2528 13
Fastjson远程代码执行漏洞,阿里云AI安全为您保驾护航
|
14天前
|
人工智能 自然语言处理 数据挖掘
Qwen3.8-Max-Preview深度全解析:2.4万亿参数旗舰MoE模型+Token Plan限时优惠完整落地指南
2026年7月,全新旗舰级混合专家大模型Qwen3.8-Max-Preview正式开放抢先体验,作为通义千问Qwen3系列规格最高、综合推理能力顶尖的新一代模型,该模型总参数量达到2.4万亿(2.4T),是当前线上可调用的原生多模态旗舰模型,综合推理水准对标海外顶级Fable 5模型,在复杂工程开发、长文档深度分析、多步骤智能体自治、跨境多语言创作、海量数据挖掘五大高难度业务场景实现跨越式性能提升。
1395 2
|
12天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
1368 2
|
16天前
|
人工智能
Qwen3.8抢先体验!正式版即将发布并开源!
千问Qwen3.8即将开源,参数达2.4T,进化速度以“天”计,实力媲美Fable 5。预览版Qwen3.8-Max已上线阿里Token Plan等平台,限时优惠:日间Credits低至1折,夜间更优,个人/团队版月付仅35元起!
1443 55