Spring作为当今风靡世界的Web领域的第一框架,作为一名Java开发程序员是一定要掌握的,除了需要掌握基本的使用之外,更需要掌握其实现原理,因为我们往往在开发的过程中,会出现各种各样的异常问题。而且这样的问题去百度有时候往往也找不到特别有效的解决方法,因为问题的原因非常多而百度的又不准确,这个时候怎么办呢?在熟练掌握Spring代码的情况下,我们可以根据提示的异常信息,去跟到源代码的地方,可以准确的定位到异常的所在,这就犹如debug调试自己的业务逻辑一样轻松了,所以Spring的源代码非常值得一读。还有另外一个好处就是,Spring的构建非常的复杂,但同时它的设计也是非常的灵性的,不仅对我们自身的软件设计能力会有很大的提高,感受到软件设计的魅力所在。其实我本来是想等我把Spring的代码完全读透之后再写下这些博文,但是感觉写博客就相当于对自己的一个总结,可能边分析边学下来比较好,下面,就让我来一点一点分析Spring的源码。

  Spring家族的构成非常的庞大,网上有很多图,我也随手拎了一张过来,如下图所示:

  通过这张图,我们可以看到处于最下面的是Beans、Core、Context和SpEl四个模块,SpEl是Spring的一个表达式,并没有那么重要,所以我们暂时就不去分析这个了。重点讲一讲其他的三个模块。我借用淘宝大神许令波在《深入分析Web技术内幕》一书中的比喻,Beans相当于Java的对象,而Java对象封装了数据,一个IOC容器中往往会有很多的Bean,我们在这里可以将Bean比喻成演员。Context就相当于容器,给演员,也就是Bean提供了一个舞台,那么最后演员有了,舞台也有了,每个演员不可能只会自己演自己的,也不可能没有道具和服装,所以这个时候Core组件排上用场了,按照这么说的话,Core组件可以维护每个Bean之间的关系,也就相当于这些演员在舞台上要演出的“道具”和“服装”等等。如果这个比喻你还不能理解的话,可以再打一个比喻。三国演义中,每个主公都有自己的武将,可以把武将就看作一个Bean,主公作为一城之主,当敌人来犯的时候必须调配武将,给他们分配兵马,而且打仗的时候需要各个武将之间的配合方能取胜,这个时候我们就可以把主公当作一个容器,主公分发的兵马,粮草器械等等是Core组件,这个用来维持每个武将之间的关系。这三者之间的关系大概就是这样了,只要理解了其实很多情景都可以用IOC来解释了。今天我们就主要说说IIOC三大组件之一的Bean组件。

  首先我们要知道Bean组件是怎么设计的,有哪些类和接口定义了这些功能,画出UML图来表示这些结构和组成。Bean组件位于Spring的org.springframework.beans包下面,如图所示:

这个包其实解决了三件事情:Bean的定义、Bean的创建和Bean的解析。而我们在使用Spring框架的时候要做的就是完成Bean的创建,也就是编写配置文件。Spring的Bean组件的实现完全上是一个工厂模式,位于最顶层的是一个名叫BeanFactory的接口,IOC功能的Bean组件的类结构如下图所示:

最终的实现类是DefaultListableBeanFactory,它实现了所有的接口和类。最顶层的类是BeanFactory,从字面的意思可以理解为bean工厂,是bean组成的最基本的类。它有三个子接口:ListableBeanFactory、HierarchicalBeanFactory和AutowireCapableBeanFactory三个接口。这三个接口的功能肯定是不一样的,分别将代码贴出来。

ListableBeanFactory:这个接口的Bean工厂表示里面的bean元素是可列表的

 package org.springframework.beans.factory;

 import java.lang.annotation.Annotation;
import java.util.Map; import org.springframework.beans.BeansException; public interface ListableBeanFactory extends BeanFactory { boolean containsBeanDefinition(String beanName);
    
int getBeanDefinitionCount(); String[] getBeanDefinitionNames();
  
String[] getBeanNamesForType(Class<?> type);
    
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit); <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException; <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException; Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
throws BeansException; <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType);
}

HierarchicalBeanFactory:这个接口的Bean表示这些Bean是有继承关系的。

 package org.springframework.beans.factory;

 public interface HierarchicalBeanFactory extends BeanFactory {

     BeanFactory getParentBeanFactory();

     boolean containsLocalBean(String name);

 }

AutowireCapableBeanFactory:表示Bean是可以自动装配的。

 package org.springframework.beans.factory.config;

 import java.util.Set;

 import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory; public interface AutowireCapableBeanFactory extends BeanFactory { int AUTOWIRE_NO = 0; int AUTOWIRE_BY_NAME = 1; int AUTOWIRE_BY_TYPE = 2; int AUTOWIRE_CONSTRUCTOR = 3; @Deprecated
int AUTOWIRE_AUTODETECT = 4; //-------------------------------------------------------------------------
// Typical methods for creating and populating external bean instances
//------------------------------------------------------------------------- <T> T createBean(Class<T> beanClass) throws BeansException; void autowireBean(Object existingBean) throws BeansException; Object configureBean(Object existingBean, String beanName) throws BeansException; Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException; //-------------------------------------------------------------------------
// Specialized methods for fine-grained control over the bean lifecycle
//------------------------------------------------------------------------- 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; Object initializeBean(Object existingBean, String beanName) throws BeansException; Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException; Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException; Object resolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException; }

这四个接口共同定义了Bena的集合,Bean之间的关系和Bean的行为。

Bean的定义

Bean的定义主要由BeanDefinition描述,类的结构图如下:

Bean的解析

Bean解析的过程非常的复杂,功能被分得很细,因为这里需要被扩展的地方很多,必须保证有足够的灵活性,以应对可能的变化。Bean的解析主要就是对Spring配置文件的解析,这个解析过程如图所示:

以上就包括了Spring IOC中的Bean组件的一些基本的定义和类的结构,请大家参考。

Spring源码分析之IOC容器(一)的更多相关文章

  1. 【spring源码分析】IOC容器初始化(总结)

    前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...

  2. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  3. 【spring源码分析】IOC容器初始化(三)

    前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...

  4. 【spring源码分析】IOC容器初始化(四)

    前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...

  5. 【spring源码分析】IOC容器初始化(七)

    前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...

  6. 【spring源码分析】IOC容器初始化(十)

    前言:前文[spring源码分析]IOC容器初始化(九)中分析了AbstractAutowireCapableBeanFactory#createBeanInstance方法中通过工厂方法创建bean ...

  7. 【spring源码分析】IOC容器初始化——查漏补缺(一)

    前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...

  8. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

  9. 【spring源码分析】IOC容器初始化——查漏补缺(五)

    前言:我们知道在Spring中经常使用配置文件的形式对进行属性的赋值,那配置文件的值是怎么赋值到属性上的呢,本文将对其进行分析. 首先了解一个类:PropertySourcesPlaceholderC ...

  10. 【spring源码分析】IOC容器初始化——查漏补缺(二)

    前言:在[spring源码分析]IOC容器初始化(八)中多次提到了前置处理与后置处理,本篇文章针对此问题进行分析.Spring对前置处理或后置处理主要通过BeanPostProcessor进行实现. ...

随机推荐

  1. 未能加载“xxx”程序集

    找到程序集名称,去项目文件中查找是否拥有.

  2. 使用 RetroShare 分享资源

    本文告诉大家如何使用 RetroShare 来分享资源.因为 RetroShare 是一个 p2p 分享的工具,所以他比现在很多云盘都好用,在网上,很多大神说可以用来代替电驴.之所以推荐这个软件,因为 ...

  3. sql count执行速度测试

    要对数据库里面的数据数量进行统计使用,数据库的大概有2000w多的数据.数据库是mysql5.6 用的是远程连接测试 ELECT COUNT(*) 执行语句: select count( *) fro ...

  4. Freemarker详解一

    1 截取字符串有的时候我们在页面中不需要显示那么长的字符串,比如新闻标题,这样用下面的例子就可以自定义显示的长度<#if title.content?length lt 8>        ...

  5. VMWare安装Mac OS X

    原文作者 谷月K 2016.08.16 18:55 字数3473 随着iPhone.iPad.Mac等苹果产品越来越火爆,越来越多的初学者想要了解和尝试苹果平台,包括苹果操作系统Mac OS X.苹果 ...

  6. Java8简明学习之Optional

    Java在8的版本,新增了Optional和lambda表达式,使得日常开发中对于NullPointException的判断变的优雅. 现在来个例子看看在Optional之前对空的判断. @Test ...

  7. 【学习笔记】--- 老男孩学Python,day8 知识点补充 join,列表不能循环删除,深浅copy

    1. 补充基础数据类型的相关知识点 1. str. join() 把列表变成字符串 2. 列表不能再循环的时候删除. 因为索引会跟着改变 3. 字典也不能直接循环删除. 把要删除的内容记录在列表中. ...

  8. sublime3中如何快速生成html头部信息

    前提要安装Emmet 插件:已经结束了啊,不要以为下面的操作跟问题有关,下面是具体的生成头部信息方法 输入下边加粗的缩写,然后Tab,就可以了: 生成html4.01 Transitional用 ht ...

  9. 重装系统,打开VS进行程序调试运行的时候 Unable to find manifest signing certificate in the certificate store

    重装系统,打开VS进行程序调试运行的时候 Unable to find manifest signing certificate in the certificate store. 项目的属性-> ...

  10. lombok的简单介绍(2)

    在和idea中整合遇到这样问题,实体对象不提示lombok的get/set方法,从网上找到以下方法,分享给大家