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修饰, 那么这个静态成员其实不是实例的, 它是类的。


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


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


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

相关文章
|
1天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
23 8
|
14天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
14天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
1月前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
144 5
|
27天前
|
XML 安全 Java
Spring Boot中使用MapStruct进行对象映射
本文介绍如何在Spring Boot项目中使用MapStruct进行对象映射,探讨其性能高效、类型安全及易于集成等优势,并详细说明添加MapStruct依赖的步骤。
|
3月前
|
NoSQL Java Redis
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
这篇文章介绍了Redis的基本命令,并展示了如何使用Netty框架直接与Redis服务器进行通信,包括设置Netty客户端、编写处理程序以及初始化Channel的完整示例代码。
83 1
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
|
3月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
120 2
|
3月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
329 1
|
3月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
43 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
3月前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
49 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
下一篇
开通oss服务