SpringBoot (走读源码)静态方法中调用spring注入的对象,注入对象为null?

简介: SpringBoot (走读源码)静态方法中调用spring注入的对象,注入对象为null?

大家都开始玩springboot了, 其实肯定已经知道 平常写代码,如果在静态方法里面调用 spring ioc容器里面的bean,是不允许的。


就像这样,在写代码的时候就告诉你不能这么写:


image.png


然后我们根据提示,改成这样写哈哈哈哈, 可以了(静态拿静态,没毛病):


image.png


然后我们真正去调用,会发现报错:


image.png 


取出来的tradeService 是null :


image.png


为什么?  怎么办 ?



怎么办我不展开说其实很多方案,可以把这个tardeService直接拿出来。


我这一篇文章想给大家讲讲是为什么 ?


我觉得大部分人可能都不会去关注这个东西。

静态方法提前加载啊, 肯定拿不到bean的实例啦 ,这么理解确实没有错。


我抛出一个问题:


如果给你去实现,我就要你静态方法加载的时候,去取实例,你去封装一下spring框架,


你能不能实现 ?


答案是: 必然可以的。


所以我现在要揭开 为什么不能的真面目了



源码:


AutowiredAnnotationBeanPostProcessor 的 buildAutowiringMetadata 函数,看到那个isStatic方法了么?


image.png


没错,其实就是spring框架这里拦截判断如果是static,直接return,不再注入,所以后面我们拿到null了。


可能这么一句话说,看不懂源码的初学者可能不太信。


OK,那我现在就通过debug方式,魔改一下这个判断。


①首先我把debug打好,卡在前面:


image.png


②来了,主角来了:


image.png


③ 动手:


可以看到 isStatic()的源码,


 image.png


也就是说如果 field.getModifiers() 改成0,就能绕过这个静态检测 。


就这么做,直接改成0:


 image.png


ps: 评论区有兄弟对这个改debug的值感兴趣,我补一张操作图,平时dubug调试的时候,看个人使用习惯,也可以这样去调试一些业务场景。


image.png


可以看到成功绕过了,绕过后立刻改回来还原原来的值 10:


image.png


如果被拦截是有日志打印的:


image.png


现在我们绕过之后:


image.png


现在我们再来调用一下看看效果,不再是null了:


image.pngimage.png


看到这里,大家都知道为啥了、 就是 spring 的作者在设计上的考虑,这个isStatic就是真凶。


深思



从做开源框架的角度上去考虑, 是不是什么都做,是好框架?


那么spring容器的职责、初衷是什么?


(当然,现在这一小段分析都是我个人的想法,可能不够成熟。)


IOC的初衷,是用来管理 bean的实例的。


如果说一个属性是 static修饰, 那么这个静态成员其实不是实例的, 它是类的。


不是我们的饭, 我们能吃,但是能够吃么? 该吃么? 什么时候会去吃?


别说光看这个问题了,不管工作上,生活中,我们是不是都应该想一想。


如果你有看法,欢迎留言。

相关文章
|
11月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
860 2
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
7658 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
存储 JSON Java
1059 0
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1580 3
|
机器学习/深度学习 数据采集 人机交互
springboot+redis互联网医院智能导诊系统源码,基于医疗大模型、知识图谱、人机交互方式实现
智能导诊系统基于医疗大模型、知识图谱与人机交互技术,解决患者“知症不知病”“挂错号”等问题。通过多模态交互(语音、文字、图片等)收集病情信息,结合医学知识图谱和深度推理,实现精准的科室推荐和分级诊疗引导。系统支持基于规则模板和数据模型两种开发原理:前者依赖人工设定症状-科室规则,后者通过机器学习或深度学习分析问诊数据。其特点包括快速病情收集、智能病症关联推理、最佳就医推荐、分级导流以及与院内平台联动,提升患者就诊效率和服务体验。技术架构采用 SpringBoot+Redis+MyBatis Plus+MySQL+RocketMQ,确保高效稳定运行。
1021 0
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
1360 1
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
1039 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
935 7