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


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


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


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

相关文章
|
Java Spring 容器
如何解决spring EL注解@Value获取值为null的问题
本文探讨了在使用Spring框架时,如何避免`@Value("${xxx.xxx}")`注解导致值为null的问题。通过具体示例分析了几种常见错误场景,包括类未交给Spring管理、字段被`static`或`final`修饰以及通过`new`而非依赖注入创建对象等,提出了相应的解决方案,并强调了理解框架原理的重要性。
864 5
|
9月前
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——使用 fastJson 处理 null
本文介绍如何使用 fastJson 处理 null 值。与 Jackson 不同,fastJson 需要通过继承 `WebMvcConfigurationSupport` 类并覆盖 `configureMessageConverters` 方法来配置 null 值的处理方式。例如,可将 String 类型的 null 转为 "",Number 类型的 null 转为 0,避免循环引用等。代码示例展示了具体实现步骤,包括引入相关依赖、设置序列化特性及解决中文乱码问题。
510 0
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
366 12
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
509 12
|
XML 安全 Java
Spring Boot中使用MapStruct进行对象映射
本文介绍如何在Spring Boot项目中使用MapStruct进行对象映射,探讨其性能高效、类型安全及易于集成等优势,并详细说明添加MapStruct依赖的步骤。
508 0
|
前端开发 Java Spring
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
【Spring】“请求“ 之传递单个参数、传递多个参数和传递对象
418 2
|
Java Spring
获取spring工厂中bean对象的两种方式
获取spring工厂中bean对象的两种方式
190 1
|
存储 Java 程序员
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
本文详细讲解了Spring框架中IOC容器如何存储和取出Bean对象,包括五大类注解(@Controller、@Service、@Repository、@Component、@Configuration)和方法注解@Bean的用法,以及DI(依赖注入)的三种注入方式:属性注入、构造方法注入和Setter注入,并分析了它们的优缺点。
229 0
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
|
Java Shell C++
Springboot加载注入bean的方式
本文详细介绍了Spring Boot中Bean的装配方法。首先讲解了使用@Component、@Service、@Controller、@Repository等注解声明Bean的方式,并解释了这些注解之间的关系及各自适用的层次。接着介绍了通过@Configuration和@Bean注解定义Bean的方法,展示了其灵活性和定制能力。最后讨论了@Component与@Bean的区别,并提供了在Spring Boot应用中装配依赖包中Bean的三种方法:使用@ComponentScan注解扫描指定包、使用@Import注解导入特定Bean以及在spring.factories文件中配置Bean。
1063 0

热门文章

最新文章