前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个比较自闭的SpringIOC问题

一个比较自闭的SpringIOC问题

作者头像
用户6203048
发布2020-10-27 14:36:37
2510
发布2020-10-27 14:36:37
举报
文章被收录于专栏:JathonKatuJathonKatu

这是一个比较自闭的SpringIOC问题,有一天前同事突然找到我问这个问题。下图链接:https://www.cnblogs.com/virgosnail/p/10257040.html

(这个链接的博主其实最终还是没搞懂,或者说没说清楚)

问题大概是这样的,我有一个A类,里面有一个方法,然后我在B类中调用这个方法,然后我在C类(Controller)中new一个B类的对象,调用B类中的调用A类的方法(说到这里熟悉springIOC的同学应该知道问题了,原谅我比较菜)

一开始我被他带着节奏走,(也怪自己spring不扎实,后面需要改进)认为可能是spring的bean的生命周期的问题。debug了一晚上按下不表,我们来看看我重现的代码:(基于springBoot环境)

最深层被调用的A类:

代码语言:javascript
复制
import org.springframework.stereotype.Component;

@Component
public class AClassForIOC {
    private String a = "a";

    public String getA(){
        return a;
    }
}

调用A类的B类:

代码语言:javascript
复制
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类:

代码语言:javascript
复制
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改成如下:

代码语言:javascript
复制
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。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JathonKatu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档