当前位置: 首页 > news >正文

SpringMVC控制层private方法中出现注入的service对象空指针异常

一、现象

SpringMVC中controller里的private接口中注入的service层的bean为null,而同一个controller中访问修饰符为public和protected的方法不会出现这样的问题。

controller中的方法被AOP进行了代理,普通Controller如果没有AOP,private方法中bean也是正常的。

二、原因分析

因为没有AOP增强的private方法是正常的,所以我们可以联想到可能是因为创建了代理对象的原因导致的属性为空。

首先SpringAOP有两种实现方式,一种是Jdk动态代理,一种是Cglib动态代理。

这两种方式一种是通过对接口的实现,一种是通过创建子类重写,那么显然这两种方式都是无法代理私有方法的。

创建代理对象时会经过这么一段逻辑Enhancer#generateClass -> Enhancer#getMethods -> CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true)) -> VisibilityPredicate#evaluate

public boolean evaluate(Object arg) {Member member = (Member)arg;int mod = member.getModifiers();if (Modifier.isPrivate(mod)) {return false;} else if (Modifier.isPublic(mod)) {return true;} else if (Modifier.isProtected(mod) && this.protectedOk) {return true;} else {return this.samePackageOk && this.pkg.equals(TypeUtils.getPackageName(Type.getType(member.getDeclaringClass())));}
}

可以看到其中将私有方法进行了过滤,即创建的代理对象中并不会增强private方法

Spring中使用@Aspect注解会注册一个后置处理器,在Bean初始化时判断是否需要创建代理(主要逻辑在wrapIfNecessary方法中)。而我们都知道Bean在属性赋值时便将属性的依赖都注入了,所以此时的Bean中service层的bean是完成填充了的。

那为什么会出现调用private方法空指针异常呢?

这是因为为该类创建的代理并没有完成bean的生命周期,所以其中的属性是null。private方法并没有被真正的代理类拦截(如前面所说被过滤了),因此private方法无法获取被代理的对象,所以使用的是代理对象去调用的方法,而代理对象是由Cglib创建的并没有注入bean对象,所以出现了空指针异常。

而当调用被增强了的方法(即在代理类中重写了的方法)时,其实传入的并非代理的实例对象,而是target,即被代理的Bean的实例对象,所以才能取得service层的bean。

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {@Override@Nullablepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {// 省略...target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = invokeMethod(target, method, argsToUse, methodProxy);}else {// We need to create a method invocation...retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;// 省略...}
}static boolean isMethodProxyCompatible(Method method) {return (Modifier.isPublic(method.getModifiers()) &&method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method));
}

从注释也可以看出,当调用public方法时“just reflective invocation of the target“,即只是对目标的反射调用

相关文章:

SpringMVC控制层private方法中出现注入的service对象空指针异常

一、现象 SpringMVC中controller里的private接口中注入的service层的bean为null&#xff0c;而同一个controller中访问修饰符为public和protected的方法不会出现这样的问题。 controller中的方法被AOP进行了代理&#xff0c;普通Controller如果没有AOP&#xff0c;private方法…...

【Unity】P4 脚本文件(基础)

Unity脚本文件&#xff08;基础&#xff09;适配的C#代码编辑器如何添加一个脚本文件获取蘑菇当前位置基础代码改变物体位置帧与帧更新前言 上一篇博文主要围绕Unity Inspector部分&#xff0c;围绕组件&#xff0c;资源文件&#xff0c;父子节点部分做介绍。 链接&#xff1a;…...

(2023版)零基础入门网络安全/Web安全,收藏这一篇就够了

由于我之前写了不少网络安全技术相关的文章和回答&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人私信问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f; 要学哪些东西&#xff1f; 有哪些方向&#xff1f; 怎么选&#x…...

Vue3电商项目实战-登录模块2【05-登录-表单校验、06-登录-消息提示组件封装、07-登录-账户登录、08-登录-手机号登录、09-退出登录】

文章目录05-登录-表单校验06-登录-消息提示组件封装07-登录-账户登录08-登录-手机号登录09-退出登录05-登录-表单校验 文档&#xff1a;https://vee-validate.logaretm.com/v4/ 支持vue3.0 第一步&#xff1a;安装 执行命令 npm i vee-validate4.0.3 第二步&#xff1a;导入 …...

Python 中都有哪些常见的错误和异常?

本文首发自「慕课网」&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注&#xff01; 作者| 慕课网精英讲师 朱广蔚 Python 程序的执行过程中&#xff0c;当发生错误时会引起一个事件&#xff0c;该事件被称为异常。例如&#xff1a; 如果程…...

51单片机-1

1&#xff0c;单片机内部集成了CPU&#xff0c;RAM&#xff0c;ROM&#xff0c;定时器&#xff0c;中断系统&#xff0c;通讯接口等一系列电脑的常用硬件功能。单片机和计算机相比&#xff0c;单片机是一个袖珍版计算机 2&#xff0c;单片机里有中央处理器&#xff08;CPU&…...

【Azure 架构师学习笔记】-Azure Data Factory (4)-触发器详解-事件触发器

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Data Factory】系列。 接上文【Azure 架构师学习笔记】-Azure Data Factory (3)-触发器详解-翻转窗口 前言 事件触发指的是存储事件&#xff0c;所以在新版的ADF 中&#xff0c;已经明确了是“存储事件”&#xff0c;…...

【项目设计】高并发内存池(三)[CentralCache的实现]

&#x1f387;C学习历程&#xff1a;入门 博客主页&#xff1a;一起去看日落吗持续分享博主的C学习历程博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 也许你现在做的事情&#xff0c;暂时看不到成果&#xff0c;但不要忘记&…...

2023年,35岁测试工程师只能被“优化裁员”吗?肯定不是····

国内的互联网行业发展较快&#xff0c;所以造成了技术研发类员工工作强度比较大&#xff0c;同时技术的快速更新又需要员工不断的学习新的技术。因此淘汰率也比较高&#xff0c;超过35岁的基层研发类员工&#xff0c;往往因为家庭原因、身体原因&#xff0c;比较难以跟得上工作…...

gitlab部署使用,jenkins部署使用

gitlab部署使用&#xff0c;jenkins部署使用在线安装gitlab下载gitlab安装gitlab使用gitlab设置中文修改管理员密码创建组,创建项目,创建用户jenkins下载jenkins安装jenkin使用jenkins更改管理员密码配置拉取代码配置登录gitlab拉取代码的账号密码配置项目配置gitlab仓库配置构…...

从零开始的机械臂yolov5抓取gazebo仿真(环境搭建篇下)

sunday功能包使用介绍以及开源 sunday我给自己机械臂的命名&#xff0c;原型是innfos的gluon机械臂。通过sw模型文件转urdf。Sunday项目主要由六个功能包sunday_description、sunday_gazebo、sunday_moveit_config、yolov5_ros、vacuum_plugin、realsense_ros_gazebo组成&…...

GCC编译器 MinGW的下载安装使用教程

哎 总所周知 gcc可以用来编译C 和C。在linux广泛应用&#xff0c;那么window怎么使用gcc呢。就要用到gcc的window工具----MInGW&#xff0c;安装好之后&#xff0c;直接可以在windows的dos界面编译。下面讲解安装使用过程。1.官网下载MinGW - Minimalist GNU for Windows downl…...

【项目实战】SpringMVC配置全局属性,是实现WebMvcConfigurer接口,还是直接继承WebMvcConfigurationSupport类?

一、说明 官方推荐以下两种方式来配置全局的SpringMVC的相关属性 方式一:实现WebMvcConfigurer接口(推荐)方式二:直接继承WebMvcConfigurationSupport类。介绍一下两者区别吧。 二、 WebMvcConfigurer介绍 WebMvcConfigurer是一个接口,用于配置全局的SpringMVC的相关属…...

房产营销、地产中介如何高效低成本获客?

数字化对企业而言&#xff0c;机遇和挑战并存。房产企业可借助数字化加强日益扩大的业务规模和业务领域管理&#xff0c;以提升管理效率&#xff0c;降低管理难度&#xff1b;基于数字化技术加强客户的服务体验&#xff0c;进而收集多业态客户和场景数据&#xff0c;拓展创新业…...

Kotlin-作用域函数

在对象的上下文中执行代码块。当您在提供lambda表达式的对象上调用这样的函数时&#xff0c;它会形成一个临时作用域。在此范围内&#xff0c;可以不带名称地访问对象。这样的函数称为作用域函数。 let run with apply also 作用域函数不会引入任何新的技术功能&#xff0c;但它…...

QNX7.1 交叉编译开源库

1.下载QNX7.1 SDK并解压 ITL:~/work/tiqnx710$ ls -l 总用量 16 drwxrwxr-x 4 xxx4096 1月 28 13:38 host -rwxrwxr-x 1 xxx 972 1月 28 13:38 qnxsdp-env.bat -rwxrwxr-x 1 xxx 1676 1月 28 13:38 qnxsdp-env.sh drwxrwxr-x 3 xxx 4096 1月 28 13:38 target xxxITL:~/work/ti…...

论文投稿指南——中文核心期刊推荐(外国语言)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…...

Fabric系列 - 链码-内部链码的特性

(1)Fabric repo下的案例 Chaincode(1.4的目录结构) fabric/examples/chaincode/go ├── example02 #一个简单的转账合约 ├── eventsender #发送事件通知 ├── passthru #调用其他链码(或者其他channel的链码)example02 (转账) 一个简单的转账合约。该链码简单实…...

NetApp SnapCenter 备份管理 ——借助应用程序一致的数据备份管理,简化混合云操作

NetApp SnapCenter 简单、可扩展、赋权&#xff1a;跨 Data Fabric 的企业级数据保护和克隆管理 主要优势 • 利用与应用程序集成的工作流和预定义策略简化备份、恢复和克隆管理。 • 借助基于存储的数据管理功能提高性能和可用性&#xff0c;并缩短测试和开发用时。 • 提供基…...

Java内置队列和高性能队列Disruptor

一、队列简介 队列是一种特殊的线性表&#xff0c;遵循先入先出、后入后出&#xff08;FIFO&#xff09;的基本原则&#xff0c;一般来说&#xff0c;它只允许在表的前端进行删除操作&#xff0c;而在表的后端进行插入操作&#xff0c;但是java的某些队列运行在任何地方插入删…...

Llama-3中文优化实战:从模型选型到本地部署全解析

1. 项目概述&#xff1a;从Llama-3到中文Llama-3的进化之路 如果你在过去一年里关注过开源大模型&#xff0c;那么“Llama”这个名字对你来说一定不陌生。从Meta发布Llama-2开始&#xff0c;这个系列就成为了开源社区构建垂直领域模型的基石。今年4月&#xff0c;Meta又扔下了一…...

GPU资源利用率监测与优化实战指南

1. GPU资源利用率监测基础解析在超算中心和AI训练集群中&#xff0c;GPU资源利用率&#xff08;GPU_UTIL&#xff09;是衡量计算效率的核心指标。这个看似简单的百分比背后&#xff0c;实际上反映了GPU内部多个执行单元的综合活跃状态。通过NVIDIA的DCGM&#xff08;Data Cente…...

飞蜂窝技术:从概念到5G室内覆盖核心的实战演进

1. 从“未来可期”到“正在爆发”&#xff1a;飞蜂窝技术的十年之约在通信行业里待久了&#xff0c;你总会听到一些技术名词被反复提起&#xff0c;它们像流星一样划过天际&#xff0c;被分析师们预言将“改变一切”&#xff0c;然后……似乎又沉寂了下去。飞蜂窝&#xff08;F…...

2026出海技术观察:云API接口迭代的能力边界与业务增量空间

摘要&#xff1a;2026年AI出海告别粗放扩张&#xff0c;底层技术适配能力成为竞争核心。云API接口迭代持续优化跨境对接、算力调度与合规适配体系&#xff0c;补齐传统出海技术短板&#xff0c;为企业全球化精细化运营提供坚实支撑。一、2026 AI出海新格局&#xff1a;底层接口…...

NExT-GPT:从多模态对齐到任意模态生成的架构与实战

1. 项目概述&#xff1a;从“多模态”到“任意模态”的进化 如果你在过去一年里关注过AI领域&#xff0c;一定对“多模态大模型”这个词不陌生。从GPT-4V到Gemini&#xff0c;主流模型都在努力让AI能同时理解文本和图像。但不知道你有没有想过一个问题&#xff1a;为什么我们和…...

微信聊天记录永久备份完整指南:WeChatExporter开源工具终极教程

微信聊天记录永久备份完整指南&#xff1a;WeChatExporter开源工具终极教程 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否担心珍贵的微信聊天记录会因为手机丢失…...

为什么93%的开发者在WebRTC集成中卡在ElevenLabs音频缓冲层?——低延迟TTS流式传输终极调优方案

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs API开发接入指南 ElevenLabs 提供高质量、低延迟的语音合成&#xff08;TTS&#xff09;服务&#xff0c;其 RESTful API 支持多种语言、情感调节与声音克隆能力。接入前需在 ElevenLabs 控…...

OpenClacky:AI Agent技能加密与商业分发平台实战指南

1. 项目概述&#xff1a;从开源共享到知识变现的桥梁在AI Agent&#xff08;智能体&#xff09;生态蓬勃发展的今天&#xff0c;我们看到了一个有趣的现象&#xff1a;无数开发者贡献了海量的“技能”&#xff08;Skills&#xff09;&#xff0c;让像OpenClaw这样的平台功能日益…...

AITranslate:本地化AI翻译工作流框架,构建可编程翻译管道

1. 项目概述与核心价值最近在折腾一个挺有意思的项目&#xff0c;叫AITranslate。这名字一看就知道&#xff0c;它想用AI来干翻译的活儿。但说实话&#xff0c;现在市面上翻译工具多如牛毛&#xff0c;从老牌的谷歌翻译、DeepL&#xff0c;到各种大厂出的AI翻译插件&#xff0c…...

同样遍历 Mat,为什么你的代码慢 10 倍?

文章目录前言一、什么是不连续Mat&#xff1f;1.产生不连续内存的常见场景2.连续与不连续内存本质区别二、常见错误遍历方式&踩坑分析1.错误一:at<>()逐像素访问&#xff08;速度慢&#xff09;2.错误二&#xff1a;强行使用一维 data 指针&#xff08;高危崩溃&…...