一个比较自闭的SpringIOC问题
这是一个比较自闭的SpringIOC问题,有一天前同事突然找到我问这个问题。下图链接:https://www.cnblogs.com/virgosnail/p/10257040.html
(这个链接的博主其实最终还是没搞懂,或者说没说清楚)
问题大概是这样的,我有一个A类,里面有一个方法,然后我在B类中调用这个方法,然后我在C类(Controller)中new一个B类的对象,调用B类中的调用A类的方法(说到这里熟悉springIOC的同学应该知道问题了,原谅我比较菜)
一开始我被他带着节奏走,(也怪自己spring不扎实,后面需要改进)认为可能是spring的bean的生命周期的问题。debug了一晚上按下不表,我们来看看我重现的代码:(基于springBoot环境)
最深层被调用的A类:
import org.springframework.stereotype.Component;
@Component
public class AClassForIOC {
private String a = "a";
public String getA(){
return a;
}
}
调用A类的B类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BClassForNew {
@Autowired
AClassForIOC aClassForIOC;
public void puA(){
aClassForIOC.getA();
}
}
以及我们万恶的Controller,C类:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@RequestMapping("/test")
public void test(){
BClassForNew a = new BClassForNew();
a.puA();
}
}
然后我们调用一下:
万恶的a类居然是空的?
不出意外的,B类的方法调用抛空指针了。
于是,同事给我的结论是,可能就是因为这种调用方式导致A类没有创建。
待老夫检查一下SpringIOC容器里面是否有这些个对象啊:
因为之前读过源码,大概知道在SpringApplication.run()方法里的哪个地方能看到我们的IOC容器。
找到variables里的context->beanFactory->beanDefinitionMap。
这里beanDefinitionMap是一个ConcurrentMap,而beanDefinitionNames是一个ArrayList,前者是键值对<key:类名小驼峰,value:管理的对象>,后者是类名。beanDefinitionMap就是我们IOC容器的bean管理员本体。
从beanDefinitionMap找到了这三个对象,那么说明其实跟bean的生命周期没有什么关系。不相信的话,其实可以改一下A,B类的构造方法,打印一句话,就能在启动日志中看到,已经new了并且初始化了。
那么,为什么调用B的方法时,A是空指针?
其实答案已经呼之欲出了。
人家Spring确实把a实例对象注入到了b实例对象中。可是这里用的b实例对象并不是人家Spring构建的,而是我们自己new的,也就用不上IOC,扯不上依赖注入。自己new的对象自己负责初始化。
我们将TestController改成如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
BClassForNew bClassForNew;
@RequestMapping("/test")
public void test() {
// BClassForNew a = new BClassForNew();
// a.puA();
bClassForNew.puA();
}
}
这里我们将用Spring给我们构建的B类实例。
此时控制台没有再报错。
总结,说起来羞愧,这次的debug同事花了将近一周,我花了两天,最后我还是一步步debug才到的问题。(虽然下载了Spring源码,也没看出来,debug大法好)
除了一开始被带歪了,更重要的是我自身Spring也不算扎实。所以学习Spring源码应该提高一下优先级,毕竟菜鸡要多学学大佬的写法。希望今后不会出现这种低端bug。
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Android开发实现的IntentUtil跳转多功能工具类
- Android端“被挤下线”功能的单点登录实现
- Android轻松实现多语言的方法示例
- Android开发实现去除bitmap无用白色边框的方法示例
- Android开发实现的内存管理工具类
- Android日期和时间选择器实现代码
- Android开发实现ImageView加载摄像头拍摄的大图功能
- Android开发实现的Intent跳转工具类实例
- Android开发中的文件操作工具类FileUtil完整实例
- Android开发中超好用的正则表达式工具类RegexUtil完整实例
- Android ijkplayer的使用方法解析
- Android开发实现查询远程服务器的工具类QueryUtils完整实例
- 解决android studio 3.0 加载项目过慢问题–maven仓库选择
- Android实现朋友圈点赞列表
- Kotlin基本类型自动装箱一点问题剖析