Spring源码分析之IOC容器(一)

  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元素是可列表的

 1 package org.springframework.beans.factory;
 2
 3 import java.lang.annotation.Annotation;
 4 import java.util.Map;
 5
 6 import org.springframework.beans.BeansException;
 7
 8 public interface ListableBeanFactory extends BeanFactory {
 9
10       boolean containsBeanDefinition(String beanName);
11     
12       int getBeanDefinitionCount();
13
14       String[] getBeanDefinitionNames();
15     
16       String[] getBeanNamesForType(Class<?> type);
17     
18       String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
19
20       <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
21
22       <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
23             throws BeansException;
24
25       Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
26             throws BeansException;
27
28       <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType);
29 }   

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

 1 package org.springframework.beans.factory;
 2
 3
 4 public interface HierarchicalBeanFactory extends BeanFactory {
 5
 6
 7     BeanFactory getParentBeanFactory();
 8
 9     boolean containsLocalBean(String name);
10
11 }

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

 1 package org.springframework.beans.factory.config;
 2
 3 import java.util.Set;
 4
 5 import org.springframework.beans.BeansException;
 6 import org.springframework.beans.TypeConverter;
 7 import org.springframework.beans.factory.BeanFactory;
 8
 9 public interface AutowireCapableBeanFactory extends BeanFactory {
10
11     int AUTOWIRE_NO = 0;
12
13     int AUTOWIRE_BY_NAME = 1;
14
15     int AUTOWIRE_BY_TYPE = 2;
16
17     int AUTOWIRE_CONSTRUCTOR = 3;
18
19     @Deprecated
20     int AUTOWIRE_AUTODETECT = 4;
21
22
23     //-------------------------------------------------------------------------
24     // Typical methods for creating and populating external bean instances
25     //-------------------------------------------------------------------------
26
27     <T> T createBean(Class<T> beanClass) throws BeansException;
28
29     void autowireBean(Object existingBean) throws BeansException;
30
31     Object configureBean(Object existingBean, String beanName) throws BeansException;
32
33     Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
34
35
36     //-------------------------------------------------------------------------
37     // Specialized methods for fine-grained control over the bean lifecycle
38     //-------------------------------------------------------------------------
39
40     Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
41
42     Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
43
44     void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
45             throws BeansException;
46
47     void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
48
49     Object initializeBean(Object existingBean, String beanName) throws BeansException;
50
51     Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
52             throws BeansException;
53
54     Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
55             throws BeansException;
56
57     Object resolveDependency(DependencyDescriptor descriptor, String beanName,
58             Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
59
60 }

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

Bean的定义

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

Bean的解析

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

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

时间: 2024-10-27 05:49:32

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

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

前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正的bean对象. 总结 [spring源码分析]IOC容器初始化(一):主要分析了Spring是如何解析占位符以及BeanFactory的最终实现类DefaultListableBeanFactory. [spring源码分析]IOC容器初始化(二):以loadBeanDefinitions函数为切

【spring源码分析】IOC容器初始化(一)

前言:spring主要就是对bean进行管理,因此IOC容器的初始化过程非常重要,搞清楚其原理不管在实际生产或面试过程中都十分的有用.在[spring源码分析]准备工作中已经搭建好spring的环境,并利用xml配置形式对类进行了实例化.在test代码中有一个非常关键的类ClassPathXmlApplicationContext,在这个类中实现了IOC容器的初始化,因此我们从ClassPathXmlApplicationContext入手开始研究IOC的初始化过程. 1.ClassPathXm

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

前言:在doCreateBean方法中还遗留一个问题没有分析:循环依赖.循环依赖在Spring中是非常重要的一个知识点,因此单独进行分析. 什么是循环依赖 循环依赖就是循环引用,两个或两个以上的bean互相引用对方,最终形成一个闭环.如A依赖B,B依赖C,C依赖A.如下图所示: 循环依赖其实就是一个死循环的过程,在初始化A的时候发现引用了B,则就会去初始化B,然后发现B又引用C,则又去初始化C,在初始化C的时候,再次发现C引用了A,则又去初始化A,这样就处于死循环,除非有终结条件. Spring

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

前言:在前几篇查漏补缺中,其实我们已经涉及到bean生命周期了,本篇内容进行详细分析. 首先看bean实例化过程: 分析: bean实例化开始后 注入对象属性后(前面IOC初始化十几篇文章). 检查激活Aware接口. 执行BeanPostProcessor前置处理 实例化bean,这里会检查InitializingBean和init-method方法. 执行BeanPostProcessor后置处理 注册销毁bean的回调方法(并不是必须). 使用bean. 检查DisposableBean和

【spring源码分析】IOC容器初始化(六)

前言:经过前几篇文章的讲解,我们已经得到了BeanDefinition,接下来将分析Bean的加载. 获取Bean的入口:AbstractApplicationContext#getBean 1 public Object getBean(String name) throws BeansException { 2 // 检测bean工厂是否存活 3 assertBeanFactoryActive(); 4 return getBeanFactory().getBean(name); 5 } 分

【spring源码分析】IOC容器初始化(八)

前言:在上文bean加载过程中还要一个非常重要的方法没有分析createBean,该方法非常重要,因此特意提出来单独分析. createBean方法定义在AbstractBeanFactory中: 该方法根据给定的beanName.BeanDefinition和args实例化一个bean对象.所有bean实例的创建都会委托给该方法实现. AbstractAutowireCapableBeanFactory#createBean createBean的默认实现在AbstractAutowireCa

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

前言:本文分析InitializingBean和init-method方法,其实该知识点在AbstractAutowireCapableBeanFactory#initializeBean方法中有所提及,这里对其进行详细分析. InitializingBean InitializingBean是一个接口,它只包含一个afterPropertiesSet方法: 1 public interface InitializingBean { 2 3 /** 4 * 该方法在BeanFactory设置完了

Spring源码阅读:IOC容器的设计与实现(二)——ApplicationContext

上一主题中,了解了IOC容器的基本概念,以及BeanFactory的设计与实现方式,这里就来了解一下ApplicationContext方式的实现. ApplicationContext 在Spring的参考文档中,为啥要推荐使用ApplicationContext?它能给我们的应用带来什么好处呢?作为BeanFactory的实现之一,它又是如何设计的?在SpringMVC中使用的WebApplictionContext\XmlApplicationContext与之有何关联? Applicat

spring源码解析之IOC容器(一)

学习优秀框架的源码,是提升个人技术水平必不可少的一个环节.如果只是停留在知道怎么用,但是不懂其中的来龙去脉,在技术的道路上注定走不长远.最近,学习了一段时间的spring源码,现在整理出来,以便日后温故知新. IOC容器是spring最核心的模块之一,是整个spring体系的基石,spring其他模块中,都需要用到IOC容器的功能.spring框架为我们提供了多种IOC容器,DefaultableBeanFact ory.FileSystemXmlApplicationContext.Class