搭建好源码阅读环境后,就可以慢慢走进Spring殿堂了。IOC是Inversion of Control的缩写,控制反转的意思。很多人可能都知道IOC是spring的核心,将对象的创建初始化等权限交由容器控制,从而减少对象之间的依赖。甚至听说过BeanFactory,知道BeanFactory是实现IOC机制的核心,但是具体如何实现,却不是十分清楚。下面我们来一步一步深入理解BeanFactory。

引例

在spring工程应用中,一般用spring注解@Autowired来自动加载依赖对象,如下所示:

  1. public class MerchantController {
  2. @Autowired
  3. private final MerchantService merchantService;
  4. }

注解@Autowired使得对象加载很方便,使得对象依赖间管理很容易。但是依据守恒定律,对象的加载、创建、初始化等步骤是不会减少的,这里使用简单了,那必然在别的地方执行了对象的加载、创建、初始化的过程。实际上这个加载、创建、初始化的过程是在Spring源码BeanFactory中完成的。

BeanFactory

首先看下BeanFactory源码,BeanFactory是一个祖宗级接口,定义了Bean Factory的各种基本方法。spring中各种具体bean工厂均是对BeanFactory接口的实现,如DefaultListableBeanFactory,SimpleJndiBeanFactory,StaticListableBeanFactory等。

作为一个接口,BeanFactory定义的方法非常简单,而且都是一些常用的方法模板,如:getBean()containsBean()isSingleton()方法。BeanFactory接口如下:

  1. package org.springframework.beans.factory;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.core.ResolvableType;
  4. public interface BeanFactory {
  5. String FACTORY_BEAN_PREFIX = "&";
  6. Object getBean(String name) throws BeansException;
  7. <T> T getBean(String name, Class<T> requiredType) throws BeansException;
  8. <T> T getBean(Class<T> requiredType) throws BeansException;
  9. Object getBean(String name, Object... args) throws BeansException;
  10. <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
  11. boolean containsBean(String name);
  12. boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
  13. boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
  14. boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
  15. boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
  16. Class<?> getType(String name) throws NoSuchBeanDefinitionException;
  17. String[] getAliases(String name);
  18. }

顾名思义,getBean()方法是用来获取Bean工厂中存储的对象实例,根据name即可获得对应的对象,也即是配置文件(暂认为xml)中定义的idcontainsBean是用于判断该Bean工厂中是否含有name所对应的对象。isSingleton是判断该name所对应的Bean是否是共享的单例,如果true的话,当调用getBean()方法时便会返回该Bean。

getBean()方法,应该能够猜测出:Bean工厂是先将name-bean作为一个键值对存储在一个容器中,当调用getBean()方法时,根据key值取出对应的bean值。实际上,spring中的确是这么做的。

根据UML类图关系,找到BeanFactory接口对应的默认实现类DefaultListableBeanFactory,如下图所示。

查看DefaultListableBeanFactory源码,发现:属性中beanDefinitionMap用于存储name-bean键值对,也即是存放Bean工厂实例化后的bean。截取部分源码如下:

  1. package org.springframework.beans.factory.support;
  2. @SuppressWarnings("serial")
  3. public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
  4. implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
  5. ............
  6. /** Map of bean definition objects, keyed by bean name */
  7. private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
  8. ...........
  9. }

从源码可以发现,存储键值对的容器是ConcurrentHashMap,它是一个基于HashMap的高并发容器,具有很好的线程安全性。其存储的不是String-Object键值对,而是String-BeanDefinition键值对,也就是说创建的bean对象不是以Object类型存储的,而是Bean Definition类型存储。为什么是这样的呢?请听下回分解

Spring IOC容器分析(1) -- BeanFactory的更多相关文章

  1. Spring IOC容器分析(2) -- BeanDefinition

    上文对Spring IOC容器的核心BeanFactory接口分析发现:在默认Bean工厂DefaultListableBeanFactory中对象不是以Object形成存储,而是以BeanDefin ...

  2. Spring IOC容器分析(4) -- bean创建获取完整流程

    上节探讨了Spring IOC容器中getBean方法,下面我们将自行编写测试用例,深入跟踪分析bean对象创建过程. 测试环境创建 测试示例代码如下: package org.springframe ...

  3. Spring IOC容器分析(3) -- DefaultListableBeanFactory

    上一节介绍了封装bean对象的BeanDefinition接口.从前面小结对BeanFactory的介绍中,我们知道bean对象是存储在map中,通过调用getBean方法可以得到bean对象.在接口 ...

  4. Spring IoC容器的设计——BeanFactory应用场景

    1.BeanFactory提供的是最基本的IoC容器的功能,关于这些功能定义,我们可以在接口BeanFatory中看到. 2.BeanFactory接口定义了IoC容器最基本的容器的形式,并且提供了I ...

  5. Spring IoC容器的设计——BeanFactory应用场景2

    1.BeanFactory接口设计了getBean方法,这个方法是使用IoC容器API的主要方法,通过这个方法,可以取得IoC容器中管理的Bean,Bean的取得是通过指定名字来索引的. 2.如果需要 ...

  6. spring揭密学习笔记(3)-spring ioc容器:Spring的IoC容器之BeanFactory

    1. Spring的IoC容器和IoC Service Provider的关系 Spring的IoC容器和IoC Service Provider所提供的服务之间存在一定的交集,二者的关系如图4-1所 ...

  7. Spring Ioc容器核心类继承图

    Spring IOC容器其实就是BeanFactory的实例,Spring中BeanFactory的类关系结构如下图: 从上图可以看出Beanfactory作为根接口又细化出三个二级接口,最后又有Co ...

  8. Spring源码分析:Spring IOC容器初始化

    概述: Spring 对于Java 开发来说,以及算得上非常基础并且核心的框架了,在有一定开发经验后,阅读源码能更好的提高我们的编码能力并且让我们对其更加理解.俗话说知己知彼,百战不殆.当你对Spri ...

  9. 【spring源码分析】spring ioc容器之前生今世--DefaultListableBeanFactory源码解读

    spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,因此可以这么说, DefaultL ...

随机推荐

  1. Sets 比赛时想错方向了。。。。 (大数不能处理负数啊)

    Sets Time Limit: 6000/3000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus P ...

  2. NOIP2017SummerTraining0714

    个人感受:第一题做了字典树,还运行错误,然后就弃疗了,然后水了二三两题,总共拿了85分,倒数. 正确答案 时间限制: 2 Sec  内存限制: 256 MB提交: 702  解决: 82[提交][状态 ...

  3. ES中const

      前  言 EScript 上一次总结了,ES中let和var的区别,今天在带大家了解另一个声明关键词:const. const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改 ...

  4. 使用路由延迟加载 Angular 模块

    使用路由延迟加载 Angular 模块 Angular 非常模块化,模块化的一个非常有用的特性就是模块作为延迟加载点.延迟加载意味着可以在后台加载一个模块和其包含的所有组件等资源.这样 Angular ...

  5. Ubuntu12.04 Firefox安装flash

    1. 实验环境 Ubuntu 14.04x86 2.安装步骤 2.1 浏览器访问:https://get.adobe.com/flashplayer/?loc=cn 2.2 网址会自动识别ubuntu ...

  6. HDU1257 最少拦截系统 (贪心+STL+二分)

    第一次在博客园写博客,好紧张 .博客搬家居然很多代码成了乱码,欲哭无泪,妈咪. 开学东西太多了吧,没时间写备注,有点时候只能贴个代码,以后有时间再加备注吧,只贴代码不是好习惯. 咦,贪心怎么写,我只会 ...

  7. 调用js中文乱码

    JS文件是GB2312编码的,如果需要js中的中文不出现乱码,在UTF-8编码中调用语句为: <script src="myjs001.js" charset="g ...

  8. 第三章 MySQL高级查询(一)

    第三章 MySQL高级查询(一) 一.SQL语言的四个分类 1.       DML(Data Manipulation Language)(数据操作语言):用来插入,修改和删除表中的数据,如INSE ...

  9. [置顶] 一个demo学会css

    全栈工程师开发手册 (作者:栾鹏) 一个demo学会css css选择器全解 css操作语法全解 学习了css权威指南这本书,自己喜欢边学边总结边写demo,所以写了这篇文章,包含了大部分的css编程 ...

  10. 使用下一代web开发框架koa2搭建自己的轻服务器

    Koa 是由 Express 原班人马亲情打造的新一代web框架.既然已经有 Express 了,为什么又要搞一个Koa出来呢?因为 Koa 相比 Express 体积更小,代码更健壮,作用更纯粹. ...