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. Robust Locally Weighted Regression 鲁棒局部加权回归 -R实现

    鲁棒局部加权回归 [转载时请注明来源]:http://www.cnblogs.com/runner-ljt/ Ljt 作为一个初学者,水平有限,欢迎交流指正. 算法参考文献: (1) Robust L ...

  2. Linux 用户打开进程数的调整

    Linux 用户打开进程数的调整 参考文章: 关于RHEL6中ulimit的nproc限制(http://www.cnblogs.com/kumulinux/archive/2012/12/16/28 ...

  3. 【Qt编程】Qt学习之窗口间的相互切换

    在用Qt设计GUI时,经常要设计两个窗口之间的相互切换,即可以从一个窗口跳转到另一个窗口,然后又从另一个窗口跳转回原窗口.下面我们来介绍具体的实现方法: 工程建立及功能描述: 首先,我们建立Qt  G ...

  4. LeetCode之“链表”:Linked List Cycle && Linked List Cycle II

    1.Linked List Cycle 题目链接 题目要求: Given a linked list, determine if it has a cycle in it. Follow up: Ca ...

  5. Gradle 1.12用户指南翻译——第三十章. CodeNarc 插件

    其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...

  6. The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files

    The type java.lang.Object cannot be resolved.It is indirectly referenced from required .class files ...

  7. Android全局异常处理 实现自己定义做强制退出和carsh日志抓取

    在做android项目开发时,大家都知道都会遇到程序报错或者Anr异常,会弹出来一个强制退出的弹出框,对于开发人员是好事,但是对于用户体验和 UI实在毫无违和感,别说用户接受不了,就连我们自己本身可能 ...

  8. PS 滤镜——平面坐标变换到极坐标

    %%% orthogonal coordinate to polar coordinate %%% 平面坐标转极坐标 clc; clear all; close all; addpath('E:\Ph ...

  9. Linux内核中断和异常分析(上)

    中断,通常被定义为一个事件.打个比方,你烧热水,水沸腾了,这时候你要去关掉烧热水的电磁炉,然后再去办之前手中停不下来的事情.那么热水沸腾就是打断你正常工作的一个信号机制.当然,还有其它的情况,我们以后 ...

  10. 巨高兴,偶的文章 “如何在服务器上配置ODBC来访问本机DB2for Windows服务器”被推荐至CSDN博客首页

    非常高兴,偶的文章 "如何在服务器上配置ODBC来访问本机DB2for Windows服务器"被推荐至CSDN博客首页,截图留念.                  文章被推荐在C ...