spring是我经常使用的框架,可是你真的对spring理解吗? 还是只知道它得使用。如果你想知道它真实的面目请仔细向下看。

1.spring是如何知道哪些Bean需要实例化的?

容器启动过程中,首先调用DispatcherSerlvet的init方法,init方法内部根据web.xml的配置,读取配置的上下文readspring-servlet.xml,然后逐句解析该上下文,当它读取到context:component-scan标签时,就启动对应的解析器,也可以叫做扫描器,对应的Class为:ComponentScanBeanDefinitionParser。这个类ComponentScanBeanDefinitionParser中调用了doScan方法,可以看到传了一个参数:basePackages,就是我们配置的路径。

这样,就读取到了需要被实例化的所有类,之后这些类的信息会被封装成一个一个的BeanDefinition,然后保存到DefaultListableBeanFactory的beanDefinitionMap中供后续使用。

    /** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

2.Spring中Bean是什么时候被实例化的?

所有的这些Bean,在容器启动的时候,已经全部被实例化了。

下面看代码一探究竟,还得看模板方法,AbstractApplicationContext.refresh(),其中有这么一个方法

  // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

看注释知道:实例化剩下的所有单例。

Spring中的Bean默认都是单例的,除非显示的声明为prototype。

剩下的(remaining)的意思是有一些Spring自身的处理器、解析器等Bean不是在这里实例化的,我们自己编写的常规类Controller、Service等全部都是在此处实例化。

3.实例化的过程

首先循环所有的BeanDefinition列表,然后调用getBean()方法,检查是否被实例化,如果没有被实例化则调用createBean()方法,具体的实例化是利用cglib类库,通过Java反射原理,构造函数实例化方式去实例化。然后组装Bean,把Bean属性设置进去,这里就是依赖注入了,把实例化好的serviceInstance注入到Service中。实例化成功后将实力保存到singletonObjects Map中。

所有的Bean被实例化后,会被存入这个Map中供后续使用。

DefaultSingletonBeanRegistry.java

    /** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>();

4.Bean的Scope

  (1)Singleton:一个Spring容器中只有一个Bean的实例,此为Spring的默认配置,全容器共享一个实例。

  (2)Prototype:每次调用新建一个Bean实例。

  (3)Request:Web项目中,给每一个 http request 新建一个Bean实例。

  (4)Session:Web项目中,给每一个 http session 新建一个Bean实例。

  (5)GlobalSession:这个只在portal应用中有用,给每一个 global http session 新建一个Bean实例。

其中request,session和global session只适用于Web应用程序中,通常是与XmlWebApplicationContext一起使用,在实现上,singleton和prototype两种类型的容器的标准类型,而Scope request,session和global session是继承于自定义的Scope接口,如果用户有特殊的需要,可以继承这个接口并注册到容器中,即可使用用户自定义的Scope类型。用户自定义的Scope必须自己维护所管辖对象的初始化及销毁,即容器将这些对象的生存周期委托给Scope管理,而容器只管理Scope对象本身就可以。

5. 注解怎么做到声明接口就可以将实现类注入?

Spring主要利用了Class.isAssignableFrom()方法来实现接口与实现类的匹配。

  Class1.isAssignableFrom(Class2):如果Class1是Class2本身或者是其接口或者父类,则返回true,否则返回false;

以testService的实例化为例,当Spring容器启动的时候,首先会读取配置文件,经过定位、加载、解析、注册,最终把标注了注解的类(例如:标注了@Service的TestServiceImpl)注册到BeanDefination的Map中并且缓存。

然后,在实例化testService的时候,Spring此刻并不知道testService的实现类是哪个,而是循环遍历BeanDefinitionMap中的Bean,逐一与ITestService接口进行类型匹配,一旦匹配上就认定为其实现类,并对其进行实例化。

参考----http://www.cnblogs.com/notDog/p/5420727.html

https://www.cnblogs.com/dyppp/p/7397290.html

https://www.imooc.com/article/19601

面试真题--------spring源码解析IOC的更多相关文章

  1. 面试真题--------spring源码解析AOP

    接着上一章对IOC的理解之后,再看看AOP的底层是如何工作的. 1.实现AOP的过程    首先我们要明白,Spring中实现AOP,就是生成一个代理,然后在使用的时候调用代理. 1.1 创建代理工厂 ...

  2. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  3. Spring源码解析-IOC容器的实现-ApplicationContext

    上面我们已经知道了IOC的建立的基本步骤了,我们就可以用编码的方式和IOC容器进行建立过程了.其实Spring已经为我们提供了很多实现,想必上面的简单扩展,如XMLBeanFacroty等.我们一般是 ...

  4. Spring源码解析-IOC容器的实现

    1.IOC容器是什么? IOC(Inversion of Control)控制反转:本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,这就叫控制反转,即交给了IOC容器,Spring的IO ...

  5. Spring源码解析--IOC根容器Beanfactory详解

    BeanFactory和FactoryBean的联系和区别 BeanFactory是整个Spring容器的根容器,里面描述了在所有的子类或子接口当中对容器的处理原则和职责,包括生命周期的一些约定. F ...

  6. spring源码浅析——IOC

    =========================================== 原文链接: spring源码浅析--IOC   转载请注明出处! ======================= ...

  7. 面试必备:ArrayList源码解析(JDK8)

    面试必备:ArrayList源码解析(JDK8) https://blog.csdn.net/zxt0601/article/details/77281231 概述很久没有写博客了,准确的说17年以来 ...

  8. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...

  9. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

随机推荐

  1. PYTHON风格规范-Google 开源项目风格指南

    Python风格规范 分号 Tip 不要在行尾加分号, 也不要用分号将两条命令放在同一行. 行长度 Tip 每行不超过80个字符 例外: 长的导入模块语句 注释里的URL 不要使用反斜杠连接行. Py ...

  2. Leetcode_136_Single Number

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42713315 Given an array of inte ...

  3. window环境下搭建react native及相关插件

    可以先浏览一下中文翻译的开发文档具体了解一下关于React Native,想要查看官方文档可以点http://facebook.github.io/react-native/docs/getting- ...

  4. Java集合之Stack

    Stack是栈,特性是先进后出(FILO,First In Last Out).Stack是继承于Vector(矢量队列),由于Vector是同数组实现的,Stack也是通过数组而非链表. Stack ...

  5. Ubuntu_ROS中应用kinect v2笔记

    Ubuntu_ROS中应用kinect v2笔记 个人觉得最重要的资料如下: 1. Microsoft Kinect v2 Driver Released http://www.ros.org/new ...

  6. Android平台根目录文件

    > 系统分区 # adb shell # mount rootfs / rootfs ro 0 0 tmpfs /dev tmpfs rw,mode=755 0 0 devpts /dev/pt ...

  7. ffplay的快捷键以及选项

    ffplay是ffmpeg工程中提供的播放器,功能相当的强大,凡是ffmpeg支持的视音频格式它基本上都支持.甚至连VLC不支持的一些流媒体都可以播放(比如说RTMP),但是它的缺点是其不是图形化界面 ...

  8. MIDlet工作原理

    题记 :  现在的J2ME用户已经是日益减少 , 开发也在转型! 无奈之下也不得不写下这系列文章来别了j2me ,也是对过去的一些总结吧! ①: 所有Kjava必须会继承自javax.microedi ...

  9. android的左右侧滑菜单实现

    最近看了很多app应用都采用的是左右侧滑,比如网易新闻.凡客等 这里也试着写一下侧滑 首先看一下效果 然后给出xml布局代码 <RelativeLayout xmlns:android=&quo ...

  10. JNI技术简介-android学习之旅(92)

    分为5步 !!!注意本地方法是java中的方法,本地函数指的是c语言中的对应函数 1.在java类中声明本地方法 2.使用javah命令,生成包含jni本地函数原型的头文件 3. 实现jni本地函数 ...