Spring IOC容器分析(1) -- BeanFactory

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

引例

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

public class MerchantController {

    @Autowired
    private final MerchantService merchantService;
}

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

BeanFactory

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

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

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;

public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);
}

顾名思义,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。截取部分源码如下:

package org.springframework.beans.factory.support;

@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    ............
    /** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
    ...........
}

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏崔庆才的专栏

Scrapy框架的使用之Scrapy对接Selenium

2194
来自专栏SeanCheney的专栏

Scrapy1.4最新官方文档总结 2 Tutorial创建项目提取信息XPath简短介绍继续提取名人名言用爬虫提取信息保存数据提取下一页使用爬虫参数更多例子

这是官方文档的Tutorial(https://docs.scrapy.org/en/latest/intro/tutorial.html)。 推荐四个Pyth...

3066
来自专栏木制robot技术杂谈

Scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250

前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo。这次我会以爬取豆瓣电影TOP250为例进一步为大家讲解一个完整爬虫的流...

3738
来自专栏Java架构沉思录

深入理解-Spring-之源码剖析IOC(一)

作为Java程序员,Spirng我们再熟悉不过,可以说比自己的女朋友还要亲密,每天都会和他在一起,然而我们真的了解spring吗?

633
来自专栏君赏技术博客

Jekyll-Admin-Mac-模板处理

制作导航条 使用网络框架Alamofire 使用 SwiftyJSON iOS10开启启用 HTTP 请求 使用 ObjectMapper ...

483
来自专栏小狼的世界

Eclipse Galileo SR2 参数配置

要崩溃了,下载了 eclipse-jee-galileo-SR2-win32.zip ,解压缩,运行后提示:

943
来自专栏程序猿DD

Spring框架中的设计模式(五)

通过以前的4篇文章,我们看到Spring采用了大量的关于创建和结构方面的设计模式。本文将描述属于行为方面的两种设计模式:命令和访问者。 前传: Spring框架...

4367
来自专栏Java Edge

Spring源码分析(一)-导读

2949
来自专栏芋道源码1024

注册中心 Eureka 源码解析 —— EndPoint 与 解析器

目前有多种 Eureka-Server 访问地址的配置方式,本文只分享 Eureka 1.x 的配置,不包含 Eureka 1.x 对 Eureka 2.x 的...

780
来自专栏微信公众号:Java团长

向Spring大佬低头——大量源码流出解析

优秀的源码中有着多年沉积下来的精华,这些精华是非常值得我们学习的。放弃阅读源码,你将失去一个和大师学习的机会。

912

扫码关注云+社区