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

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

 

springboot 调用post springboot 调用dll_springboot 调用post

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

 

springboot 调用post springboot 调用dll_加载_02

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

springboot 调用post springboot 调用dll_spring_03

 取出来的tradeService 是null :

springboot 调用post springboot 调用dll_加载_04

为什么?  怎么办 ?

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

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

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

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

我抛出一个问题:

 

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

你能不能实现 ?

答案是: 必然可以的。

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

源码:

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

springboot 调用post springboot 调用dll_spring_05

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

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

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

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


springboot 调用post springboot 调用dll_spring_06

②来了,主角来了:


springboot 调用post springboot 调用dll_静态方法_07

③ 动手:
 

可以看到 isStatic()的源码, 

 

springboot 调用post springboot 调用dll_加载_08

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

就这么做,直接改成0:
 

springboot 调用post springboot 调用dll_静态方法_09

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

springboot 调用post springboot 调用dll_springboot 调用post_10

 

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

springboot 调用post springboot 调用dll_springboot 调用post_11

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

springboot 调用post springboot 调用dll_springboot 调用post_12

 现在我们绕过之后:

springboot 调用post springboot 调用dll_springboot 调用post_13

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

springboot 调用post springboot 调用dll_静态方法_14


springboot 调用post springboot 调用dll_加载_15

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