一、BeanFactory的基本类体系结构(接口为主)

  这是我画的BeanFactory基本的类体系结构,这里没有包括强大的ApplicationContext体系,ApplicationContext我准备放到下一篇再分析。

具体:

  1、BeanFactory作为一个主接口不继承任何接口,暂且称为一级接口

  2、有3个子接口继承了它,进行功能上的增强。这3个子接口称为二级接口

  3、ConfigurableBeanFactory可以被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry

  4、ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,无所不包,称为四级接口

  (这4级接口是BeanFactory的基本接口体系。继续,下面是继承关系的2个抽象类和2个实现类:)

  5、AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分功能。

  6、AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额外实现了二级接口AutowireCapableBeanFactory

  7、DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最强大的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。

  8、最后是最强大的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些功能,使自己更强大。

总结:

  BeanFactory的类体系结构看似繁杂混乱,实际上由上而下井井有条,非常容易理解。

二、IOC的始祖——BeanFactory

  来看一下BeanFactory的源码,这么牛逼哄哄的接口就不折叠了吧:

package org.springframework.beans.factory;

public interface BeanFactory {

    /**
* 用来引用一个实例,或把它和工厂产生的Bean区分开,就是说,如果一个FactoryBean的名字为a,那么,&a会得到那个Factory
*/
String FACTORY_BEAN_PREFIX = "&"; /*
* 四个不同形式的getBean方法,获取实例
*/
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; boolean containsBean(String name); // 是否存在 boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// 是否为单实例 boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 是否为原型(多实例) boolean isTypeMatch(String name, Class<?> targetType)
throws NoSuchBeanDefinitionException;// 名称、类型是否匹配 Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 获取类型 String[] getAliases(String name);// 根据实例的名字获取实例的别名 }

具体:

  1、4个获取实例的方法。getBean的重载方法。

  2、4个判断的方法。判断是否存在,是否为单例、原型,名称类型是否匹配。

  3、1个获取类型的方法、一个获取别名的方法。根据名称获取类型、根据名称获取别名。一目了然!

总结:

  这10个方法,很明显,这是一个典型的工厂模式的工厂接口。

三、可将Bean逐一列出的工厂——ListableBeanFactory

源码:

public interface ListableBeanFactory extends BeanFactory {

    boolean containsBeanDefinition(String beanName); // 对于给定的名字是否含有BeanDefinition

    int getBeanDefinitionCount(); // 返回工厂的BeanDefinition总数

    String[] getBeanDefinitionNames(); // 返回工厂中所有Bean的名字

    String[] getBeanNamesForType(Class<?> type); // 返回对于指定类型Bean(包括子类)的所有名字

    /*
* 返回指定类型的名字 includeNonSingletons为false表示只取单例Bean,true则不是
* allowEagerInit为true表示立刻加载,false表示延迟加载。 注意:FactoryBeans都是立刻加载的。
*/
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons,
boolean allowEagerInit); <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException; // 根据类型(包括子类)返回指定Bean名和Bean的Map <T> Map<String, T> getBeansOfType(Class<T> type,
boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException; Map<String, Object> getBeansWithAnnotation(
Class<? extends Annotation> annotationType) throws BeansException; // 根据注解类型,查找所有有这个注解的Bean名和Bean的Map <A extends Annotation> A findAnnotationOnBean(String beanName,
Class<A> annotationType);// 根据指定Bean名和注解类型查找指定的Bean }

具体:

  1、3个跟BeanDefinition有关的总体操作。包括BeanDefinition的总数、名字的集合、指定类型的名字的集合。

  (这里指出,BeanDefinition是Spring中非常重要的一个类,每个BeanDefinition实例都包含一个类在Spring工厂中所有属性。)

  2、2个getBeanNamesForType重载方法。根据指定类型(包括子类)获取其对应的所有Bean名字。

  3、2个getBeansOfType重载方法。根据类型(包括子类)返回指定Bean名和Bean的Map。

  4、2个跟注解查找有关的方法。根据注解类型,查找Bean名和Bean的Map。以及根据指定Bean名和注解类型查找指定的Bean。

总结:

  正如这个工厂接口的名字所示,这个工厂接口最大的特点就是可以列出工厂可以生产的所有实例。当然,工厂并没有直接提供返回所有实例的方法,也没这个必要。它可以返回指定类型的所有的实例。而且你可以通过getBeanDefinitionNames()得到工厂所有bean的名字,然后根据这些名字得到所有的Bean。这个工厂接口扩展了BeanFactory的功能,作为上文指出的BeanFactory二级接口,有9个独有的方法,扩展了跟BeanDefinition的功能,提供了BeanDefinition、BeanName、注解有关的各种操作。它可以根据条件返回Bean的集合,这就是它名字的由来——ListableBeanFactory。

四、分层的Bean工厂——HierarchicalBeanFactory

源码:

public interface HierarchicalBeanFactory extends BeanFactory {

    BeanFactory getParentBeanFactory();    //  返回本Bean工厂的父工厂

    boolean containsLocalBean(String name);    //  本地工厂是否包含这个Bean

}

具体:

  1、第一个方法返回本Bean工厂的父工厂。这个方法实现了工厂的分层。

  2、第二个方法判断本地工厂是否包含这个Bean(忽略其他所有父工厂)。这也是分层思想的体现。

总结:这个工厂接口非常简单,实现了Bean工厂的分层。这个工厂接口也是继承自BeanFacotory,也是一个二级接口,相对于父接口,它只扩展了一个重要的功能——工厂分层。

五、自动装配的Bean工厂——AutowireCapableBeanFactory

源码:

public interface AutowireCapableBeanFactory extends BeanFactory {

    int AUTOWIRE_NO = 0;   //  这个常量表明工厂没有自动装配的Bean

    int AUTOWIRE_BY_NAME = 1;  //表明根据名称自动装配

    int AUTOWIRE_BY_TYPE = 2;  //表明根据类型自动装配

    int AUTOWIRE_CONSTRUCTOR = 3;  //表明根据构造方法快速装配

    @Deprecated
int AUTOWIRE_AUTODETECT = 4; //表明通过Bean的class的内部来自动装配(有没翻译错...)Spring3.0被弃用。 <T> T createBean(Class<T> beanClass) throws BeansException; // 根据指定Class创建一个全新的Bean实例 void autowireBean(Object existingBean) throws BeansException; // 给定对象,根据注释、后处理器等,进行自动装配 /*
* 根据Bean名的BeanDefinition装配这个未加工的Object,执行回调和各种后处理器。
*/
Object configureBean(Object existingBean, String beanName) throws BeansException; /*
* 分解Bean在工厂中定义的这个指定的依赖descriptor
*/
Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException; /*
* 根据给定的类型和指定的装配策略,创建一个新的Bean实例
*/
Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; /*
* 与上面类似,不过稍有不同。
*/
Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; /*
* 根据名称或类型自动装配
*/
void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
throws BeansException; /*
* 也是自动装配
*/
void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException; /*
* 初始化一个Bean...
*/
Object initializeBean(Object existingBean, String beanName) throws BeansException; /*
* 初始化之前执行BeanPostProcessors
*/
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException;
/*
* 初始化之后执行BeanPostProcessors
*/
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException; /*
* 分解指定的依赖
*/
Object resolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException; }

具体:

  1、总共5个静态不可变常量来指明装配策略,其中一个常量被Spring3.0废弃、一个常量表示没有自动装配,另外3个常量指明不同的装配策略——根据名称、根据类型、根据构造方法。

  2、8个跟自动装配有关的方法,实在是繁杂,具体的意义我们研究类的时候再分辨吧。

  3、2个执行BeanPostProcessors的方法。

  4、2个分解指定依赖的方法

总结:这个工厂接口继承自BeanFacotory,它扩展了自动装配的功能,根据类定义BeanDefinition装配Bean、执行前、后处理器等。

六、复杂的配置Bean工厂——ConfigurableBeanFactory

源码:

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    String SCOPE_SINGLETON = "singleton";  //  单例

    String SCOPE_PROTOTYPE = "prototype";  //  原型

    /*
* 搭配HierarchicalBeanFactory接口的getParentBeanFactory方法
*/
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException; /*
* 设置、返回工厂的类加载器
*/
void setBeanClassLoader(ClassLoader beanClassLoader); ClassLoader getBeanClassLoader(); /*
* 设置、返回一个临时的类加载器
*/
void setTempClassLoader(ClassLoader tempClassLoader); ClassLoader getTempClassLoader(); /*
* 设置、是否缓存元数据,如果false,那么每次请求实例,都会从类加载器重新加载(热加载) */
void setCacheBeanMetadata(boolean cacheBeanMetadata); boolean isCacheBeanMetadata();//是否缓存元数据 /*
* Bean表达式分解器
*/
void setBeanExpressionResolver(BeanExpressionResolver resolver); BeanExpressionResolver getBeanExpressionResolver(); /*
* 设置、返回一个转换服务
*/
void setConversionService(ConversionService conversionService); ConversionService getConversionService(); /*
* 设置属性编辑登记员...
*/
void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar); /*
* 注册常用属性编辑器
*/
void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass); /*
* 用工厂中注册的通用的编辑器初始化指定的属性编辑注册器
*/
void copyRegisteredEditorsTo(PropertyEditorRegistry registry); /*
* 设置、得到一个类型转换器
*/
void setTypeConverter(TypeConverter typeConverter); TypeConverter getTypeConverter(); /*
* 增加一个嵌入式的StringValueResolver
*/
void addEmbeddedValueResolver(StringValueResolver valueResolver); String resolveEmbeddedValue(String value);//分解指定的嵌入式的值 void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);//设置一个Bean后处理器 int getBeanPostProcessorCount();//返回Bean后处理器的数量 void registerScope(String scopeName, Scope scope);//注册范围 String[] getRegisteredScopeNames();//返回注册的范围名 Scope getRegisteredScope(String scopeName);//返回指定的范围 AccessControlContext getAccessControlContext();//返回本工厂的一个安全访问上下文 void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);//从其他的工厂复制相关的所有配置 /*
* 给指定的Bean注册别名
*/
void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException; void resolveAliases(StringValueResolver valueResolver);//根据指定的StringValueResolver移除所有的别名 /*
* 返回指定Bean合并后的Bean定义
*/
BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;//判断指定Bean是否为一个工厂Bean void setCurrentlyInCreation(String beanName, boolean inCreation);//设置一个Bean是否正在创建 boolean isCurrentlyInCreation(String beanName);//返回指定Bean是否已经成功创建 void registerDependentBean(String beanName, String dependentBeanName);//注册一个依赖于指定bean的Bean String[] getDependentBeans(String beanName);//返回依赖于指定Bean的所欲Bean名 String[] getDependenciesForBean(String beanName);//返回指定Bean依赖的所有Bean名 void destroyBean(String beanName, Object beanInstance);//销毁指定的Bean void destroyScopedBean(String beanName);//销毁指定的范围Bean void destroySingletons(); //销毁所有的单例类 }

在具体介绍之前,先看一下接口SingletonBeanRegistry的源码:

public interface SingletonBeanRegistry {

    void registerSingleton(String beanName, Object singletonObject); //在容器内注册一个单例类  

    Object getSingleton(String beanName);//返回给定名称对应的单例类

    boolean containsSingleton(String beanName);//给定名称是否对应单例类

    String[] getSingletonNames();//返回容器内所有单例类的名字

    int getSingletonCount();//返回容器内注册的单例类数量

}

可以看到,SingletonBeanRegistry这个接口非常简单,5个方法,实现了单例类注册的功能。

ConfigurableBeanFactory同时继承了HierarchicalBeanFactory 和 SingletonBeanRegistry 这两个接口,即同时继承了分层和单例类注册的功能。

具体:

  1、2个静态不可变常量分别代表单例类和原型类。

  2、1个设置父工厂的方法,跟HierarchicalBeanFactory接口的getParentBeanFactory方法互补。

  3、4个跟类加载器有关的方法:get/set工厂类加载器和get/set临时类加载器。

  4、2个设置、是否缓存元数据的方法(热加载开关)。

  5、11个处理Bean注册、加载等细节的方法,包括:Bean表达式分解器、转换服务、属性编辑登记员、属性编辑器、属性编辑注册器、类型转换器、嵌入式的字符串分解器

  6、2个处理Bean后处理器的方法。

  7、3个跟注册范围相关的方法。

  8、1个返回安全访问上下文的方法、1个从其他的工厂复制相关的所有配置的方法。

  9、2个跟Bean别名相关的方法、1个返回合并后的Bean定义的方法。

  10、1个判断是否为工厂Bean的方法、2个跟当前Bean创建时机相关的方法。

  11、3个跟Bean依赖相关的方法、3个销毁Bean相关的方法。

总结:这个巨大的工厂接口,继承自HierarchicalBeanFactory 和 SingletonBeanRegistry 这两个接口,并额外独有37个方法!!!(看的我都快疯了...)这37个方法包含了工厂创建、注册一个Bean的众多细节。这个工厂名为ConfigurableBeanFactory,真是名不虚传!统计一下此时的ConfigurableBeanFactory的方法数吧。自有的37个方法、HierarchicalBeanFactory的2个方法、SingletonBeanRegistry的5个方法、爷爷接口BeanFactory的10个方法,共有54个方法!虽然方法繁多,还算井井有条!

7、BeanFactory的集大成者——ConfigurableListableBeanFactory

源码:  

public interface ConfigurableListableBeanFactory
extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory { void ignoreDependencyType(Class<?> type);//忽略自动装配的依赖类型 void ignoreDependencyInterface(Class<?> ifc);//忽略自动装配的接口 /*
* 注册一个可分解的依赖
*/
void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue); /*
* 判断指定的Bean是否有资格作为自动装配的候选者
*/
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException; /*
* 返回注册的Bean定义
*/
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; void freezeConfiguration();//暂时冻结所有的Bean配置 boolean isConfigurationFrozen();//判断本工厂配置是否被冻结 void preInstantiateSingletons() throws BeansException;//使所有的非延迟加载的单例类都实例化。 }

具体:

  1、2个忽略自动装配的的方法。

  2、1个注册一个可分解依赖的方法。

  3、1个判断指定的Bean是否有资格作为自动装配的候选者的方法。

  4、1个根据指定bean名,返回注册的Bean定义的方法。

  5、2个冻结所有的Bean配置相关的方法。

  6、1个使所有的非延迟加载的单例类都实例化的方法。

总结:工厂接口ConfigurableListableBeanFactory同时继承了3个接口,ListableBeanFactory、AutowireCapableBeanFactory 和 ConfigurableBeanFactory,扩展之后,加上自有的这8个方法,这个工厂接口总共有83个方法,实在是巨大到不行了。这个工厂接口的自有方法总体上只是对父类接口功能的补充,包含了BeanFactory体系目前的所有方法,可以说是接口的集大成者。

8、额外的接口——BeanDefinitionRegistry

这个接口基本用来操作定义在工厂内部的BeanDefinition的。我们先来看一下这个接口的父接口:

public interface AliasRegistry {

    void registerAlias(String name, String alias);//对指定的名称注册别名

    void removeAlias(String alias);//从当前容器移除指定别名

    boolean isAlias(String beanName);//判断指定名称是否为别名

    String[] getAliases(String name);//返回指定名称的所有别名

}

可以看到这4个方法都非常简单,都是用来操作别名的。

再来看一下BeanDefinitionRegistry的源码:

public interface BeanDefinitionRegistry extends AliasRegistry {

    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException;//给定bean名称,注册一个新的bean定义 /*
* 根据指定Bean名移除对应的Bean定义
*/
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; /*
* 根据指定bean名得到对应的Bean定义
*/
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; /*
* 查找,指定的Bean名是否包含Bean定义
*/
boolean containsBeanDefinition(String beanName); String[] getBeanDefinitionNames();//返回本容器内所有注册的Bean定义名称 int getBeanDefinitionCount();//返回本容器内注册的Bean定义数目 boolean isBeanNameInUse(String beanName);//指定Bean名是否被注册过。 }

这7个方法都是用来操作容器内的BeanDefinition的。

Spring 之 BeanFactory 源码 - 接口分析的更多相关文章

  1. 十、Spring之BeanFactory源码分析(二)

    Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ...

  2. 九、Spring之BeanFactory源码分析(一)

    Spring之BeanFactory源码分析(一) ​ 注意:该随笔内容完全引自https://blog.csdn.net/u014634338/article/details/82865644,写的 ...

  3. Spring 之 BeanFactory 源码 - 抽象/类 分析

    BeanFactory的基本类体系结构(类为主):

  4. Spring IOC 容器源码分析 - 余下的初始化工作

    1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bea ...

  5. Spring IOC 容器源码分析 - 填充属性到 bean 原始对象

    1. 简介 本篇文章,我们来一起了解一下 Spring 是如何将配置文件中的属性值填充到 bean 对象中的.我在前面几篇文章中介绍过 Spring 创建 bean 的流程,即 Spring 先通过反 ...

  6. Spring IOC 容器源码分析 - 创建原始 bean 对象

    1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...

  7. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  8. Spring IOC 容器源码分析 - 获取单例 bean

    1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...

  9. Spring IOC 容器源码分析系列文章导读

    1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...

随机推荐

  1. Winform 空闲时间(鼠标键盘无操作)

    前言 Winform 在特定情况下,需要判断软件空闲时间(鼠标键盘无操作),然后在做一下一些操作. 实现 做了一个简单的例子,新建一个窗体,然后拖两个控件(Timer控件和label控件) using ...

  2. 【Markdown】Shell命令高亮显示

    [问题]shell命令,黏贴到简书的代码块上,#后面的命令显示成被注释掉的效果 image.png [目的]高亮显示shell命令 [方案1]在代码块标示符后,加上此代码块所用的语言名(请注意要用小写 ...

  3. 调试器地址出现大小端紊乱,引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。

    今天在编写一系列新增需求代码后,开始调试代码 发现上个版本正常可运行的代码出现了:引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突. 上个版本数代码 ...

  4. Java基础之(七):Scanner对象

    用户交互Scanner Scanner对象 调用java.util.Scanner 可以通过Scanner类来获取用户的输入 基本语法: Scanner scanner = new Scanner(S ...

  5. CF1082G Petya and Graph(最小割,最大权闭合子图)

    QWQ嘤嘤嘤 感觉是最水的一道\(G\)题了 顺便记录一下第一次在考场上做出来G qwqqq 题目大意就是说: 给你n个点,m条边,让你选出来一些边,最大化边权减点权 \(n\le 1000\) QW ...

  6. Redis 面试常见问题———缓存雪崩、缓存击穿以及缓存穿透

    在开发中会面临缓存异常可能会出现三个问题,分别是缓存雪崩.缓存击穿和缓存穿透.这三个问题会导致大量请求从缓存转移到数据库,如果请求的并发量很大的话,就会导致数据库崩溃.所以在面试官也会经常问这些问题. ...

  7. Longhorn 云原生容器分布式存储 - 故障排除指南

    内容来源于官方 Longhorn 1.1.2 英文技术手册. 系列 Longhorn 是什么? Longhorn 云原生容器分布式存储 - 设计架构和概念 Longhorn 云原生容器分布式存储 - ...

  8. WPF中的命令(Command)

    这节来讲一下WPF中的命令(Command)的使用. [认识Command] 我们之前说过,WPF本身就为我们提供了一个基础的MVVM框架,本节要讲的命令就是其中一环,通过在ViewModel中声明命 ...

  9. Codeforces1573B

    ### 问题描述 - 给你两个数组,a数组里面是1 - 2n中的奇数任意顺序排列组成,b数组里面是1 - 2n中的奇数任意顺序排列组成. - 问你最少需要多少次操作能让a的字典序小于b. ### 思路 ...

  10. 我们一起来回顾一下Synchronized关键字吧

    多线程一直Java开发中的难点,也是面试中的常客,趁着还有时间,打算巩固一下JUC方面知识,我想机会随处可见,但始终都是留给有准备的人的,希望我们都能加油!!! 沉下去,再浮上来,我想我们会变的不一样 ...