SpringIOC容器工作流程及源码详解

SpringIOC容器的基本工作流程

Spring 容器启动后首先是读取bean的xml配置文件,然后解析xml文件中的各种bean的定义,将xml文件中的每一个元素分别转换成一个BeanDefinition对象,其中保存了从配置文件中读取到的该bean的各种信息, 读完配置文件之后,得到了很多的BeanDefinition对象,然后通过BeanDefinitionRegistry将这些bean注册到beanFactory中, 这就是Spring IOC容器启动时的基本流程.

一、流程详解

1.首先是读取bean的xml配置文件,然后解析xml文件中的各种bean的定义,将xml文件中的每一个元素分别转换成一个BeanDefinition对象,其中保存了从配置文件中读取到的该bean的各种信息。

2.读完配置文件之后,得到了很多的BeanDefinition对象,然后通过BeanDefinitionRegistry将这些bean注册到beanFactory中。

BeanDefinitionRegisty好比Spring配置信息的内存数据库,主要是以map形式存在。在bean解析完毕的时候,
后续操作都是直接从BeanDefinitionRegisty中读取配置信息.

二、BeanDefinition详解

1、BeanDefinition中定义的属性有诸如类名、sccope、属性、构造函数参数列表、依赖的bean、是否单例类等。将Bean的定义信息存储到这个BeanDefinition相应的属性中,之后对Bean的操作就是直接对BeanDefinition进行的

2、继承 AttributeAccessor 和 BeanMetadataElement 接口
1)AttributeAccessor接口定义了对属性的修改,包括获取、设置、删除。
2)BeanMetadataElement,Bean 元对象持有的配置元素可以通过 getSource() 方法来获取。

BeanDefinition对应的就是元素的配置的属性信息,列表如下:

bean标签的属性
1)scope:**用来配置spring bean的作用域
2)singleton:**表示bean为单例的
3abstract:设置为true,将该bean仅仅作为模板使用,应用程序上下文不会试图预先初始化它
4)lazy-init:**设为true,延迟加载,该bean不会在ApplicationContext启动时提前被实例化,而是第一次向容器通过getBean索取bean时实例化
注:只对singleton的bean起作用
5)autowire:**自动装配
6)dependency-check:依赖检查
7)depends-on:**表示一个bean的实例化依靠另一个bean先实例化
8)autowire-candidate:**设为false,容器在查找自动装配对象时,将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,但是该bean本身可以使用自动装配来注入其他bean
9)primary:该bean优先被注入
10)init-method:**初始化bean时调用的方法
11)destory-method:**容器销毁之前所调用的方法
12)factory-method:当调用factory-method所指向的方法时,才开始实例化bean
13)factory-bean:调用静态工厂方法的方式创建bean
二、bean的子元素
1)meta:元数据,当需要使用里面的信息时可以通过key获取
2)lookup-method:获取器注入,是把一个方法声明为返回某种类型的bean但实际要返回的bean是在配置文件里面配置的
3)replaced-method:可以在运行时调用新的方法替换现有的方法,还能动态的更新原有方法的逻辑
4)constructor-arg:** 对bean自动寻找对应的构造函数,并在初始化的时候将设置的参数传入进去
5)property:** 基本数据类型赋值
6)qualifier:** 通过Qualifier指定注入bean的名称

对以上信息进行包装的BeanDefinition的源代码如下: ( 两个代码块可以对应着查看,是否一一对应)

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    String SCOPE_SINGLETON = "singleton"; //单例模式
    String SCOPE_PROTOTYPE = "prototype"; //原型模式(就是正常情况下的)
    
    //此bean的角色
    int ROLE_APPLICATION = 0; //表示这个bean是用户定义的
    int ROLE_SUPPORT = 1; //表示这个bean是第三方插件或工具的
    int ROLE_INFRASTRUCTURE = 2; //表示这个bean是spring内部自己的
    
    //设置or获取此bean的父bean的名字
    void setParentName(@Nullable String var1);
    @Nullable
    String getParentName();
    //设置or获取此bean的类名
    void setBeanClassName(@Nullable String var1);
    @Nullable
    String getBeanClassName();
    //设置or获取此bean的模式(单例模式还是原型模式)
    void setScope(@Nullable String var1);
    @Nullable
    String getScope();
    //设置or获取此bean的延迟初始化属性(true,false)
    void setLazyInit(boolean var1);
    boolean isLazyInit();
    //设置or获取依赖
    void setDependsOn(@Nullable String... var1);
    @Nullable
    String[] getDependsOn();
    //设置or获取此bean的是否接受被自动装配(true, false)
    void setAutowireCandidate(boolean var1);
    boolean isAutowireCandidate();
    //设置or获取是否是首要(true,false)
    void setPrimary(boolean var1);
    boolean isPrimary();
    //设置or获取工厂bean的名字
    void setFactoryBeanName(@Nullable String var1);
    @Nullable
    String getFactoryBeanName();
    //设置or 获取工厂bean里的生成方法名
    void setFactoryMethodName(@Nullable String var1);
    @Nullable
    String getFactoryMethodName();
    //获取构造函数的所有参数值
    ConstructorArgumentValues getConstructorArgumentValues();
    //判断构造函数参数是否为空
    default boolean hasConstructorArgumentValues() {
        return !this.getConstructorArgumentValues().isEmpty();
    }
    //获取所有的property
    MutablePropertyValues getPropertyValues();
    default boolean hasPropertyValues() {
        return !this.getPropertyValues().isEmpty();
    }
    //设置or获取初始化方法名
    void setInitMethodName(@Nullable String var1);
    @Nullable
    String getInitMethodName();
    //设置or获取销毁方法名
    void setDestroyMethodName(@Nullable String var1);
    @Nullable
    String getDestroyMethodName();
    //设置角色,就是前面的三个整数(0,1,2),用户定义、第三方的、spring内部的
    void setRole(int var1);
    int getRole();
    //设置or获取此bean的描述信息
    void setDescription(@Nullable String var1);
    @Nullable
    String getDescription();
    //判断此bean是否是单例、原型、抽象的
    boolean isSingleton();
    boolean isPrototype();
    boolean isAbstract();
    //获取资源描述,这个资源文件
    @Nullable
    String getResourceDescription();
 
    @Nullable
    BeanDefinition getOriginatingBeanDefinition();
}

三、 BeanDefinitionRegistry详解

定义Bean的常规操作,来注册BeanDefinition。
主要功能:
1、以Map<String, BeanDefinition>的形式注册bean
2、根据beanName 删除和获取 beanDefiniation
3、得到持有的beanDefiniation的数目
4、根据beanName 判断是否包含beanDefiniation

它的默认实现类主要有三个:SimpleBeanDefinitionRegistry、DefaultListableBeanFactory、GenericApplicationContext.

public interface BeanDefinitionRegistry extends AliasRegistry {
 
	// 关键 -> 往注册表中注册一个新的 BeanDefinition 实例 
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
	// 移除注册表中已注册的 BeanDefinition 实例
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
	// 从注册中心取得指定的 BeanDefinition 实例
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
	// 判断 BeanDefinition 实例是否在注册表中(是否注册)
	boolean containsBeanDefinition(String beanName);
	
	// 取得注册表中所有 BeanDefinition 实例的 beanName(标识)
	String[] getBeanDefinitionNames();
	// 返回注册表中 BeanDefinition 实例的数量
	int getBeanDefinitionCount();
	// beanName(标识)是否被占用
	boolean isBeanNameInUse(String beanName);
}

它的三个实现类的区别
在这里插入图片描述
SimpleBeanDefinitionRegistry 是 BeanDefinitionRegistry 一个简单的实现,它还继承 SimpleAliasRegistry( AliasRegistry 的简单实现),它仅仅只提供注册表功能,无工厂功能。SimpleBeanDefinitionRegistry 使用 ConcurrentHashMap 来存储注册的 BeanDefinition。

DefaultListableBeanFactory,它是ConfigurableListableBeanFactory(其实就是 BeanFactory ) 和 BeanDefinitionRegistry 接口的默认实现:一个基于 BeanDefinition 元数据的完整 bean 工厂。它同样是用 ConcurrentHashMap 数据结构来存储注册的 BeanDefinition。

GenericApplicationContext ,他实现注册、注销功能都是委托 DefaultListableBeanFactory 实现的.

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    //底层是将操作委托给了  DefaultListableBeanFactory 
	private final DefaultListableBeanFactory beanFactory;
    ......
}

所以我们只看 DefaultListableBeanFactory的核心源码:

// 注册表,由 BeanDefinition 的标识 (beanName) 与其实例组成
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, bean>(64);
 
// 标识(beanName)集合
private final List<String> beanDefinitionNames = new ArrayList<String>(64);
 
 
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
   throws BeanDefinitionStoreException {
 
        // 省略其他代码
 
  else {
   if (hasBeanCreationStarted()) {
    // Cannot modify startup-time collection elements anymore (for stable iteration)
    synchronized (this.beanDefinitionMap) {
     this.beanDefinitionMap.put(beanName, beanDefinition);
     List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
     updatedDefinitions.addAll(this.beanDefinitionNames);
     updatedDefinitions.add(beanName);
     this.beanDefinitionNames = updatedDefinitions;
     if (this.manualSingletonNames.contains(beanName)) {
      Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
      updatedSingletons.remove(beanName);
      this.manualSingletonNames = updatedSingletons;
     }
    }
   }
   else {
    // 注册 BeanDefinition   ****最重要的一句
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
    this.manualSingletonNames.remove(beanName);
   }
   this.frozenBeanDefinitionNames = null;
  }
 
  if (existingDefinition != null || containsSingleton(beanName)) {
   resetBeanDefinition(beanName);
  }
 }

四、BeanFactory详解

创建Bean的工厂
它最主要的方法就是 getBean(String beanName),该方法从容器中返回特定名称的 Bean,BeanFactory 的功能通过其他的接口得到不断扩展。

public interface BeanFactory {
 
    //这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
    //如果需要得到工厂本身,需要转义       
    String FACTORY_BEAN_PREFIX = "&";
 
    这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。
 
    Object getBean(String name) throws BeansException;
 
    //这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。
    Object getBean(String name, Class requiredType) throws BeansException;
 
    //这里提供对bean的检索,看看是否在IOC容器有这个名字的bean
    boolean containsBean(String name);
 
    //这里根据bean名字得到bean实例,并同时判断这个bean是不是单件
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
 
    //这里对得到bean实例的Class类型
    Class getType(String name) throws NoSuchBeanDefinitionException;
 
    //这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
    String[] getAliases(String name);
 
}

BeanFactory下最通用的一个实现是 DefaultListableBeanFactory,它同时也实现了BeanDefinitionRegistry接口,因此它就承担了Bean的注册管理工作。

DefaultListableBeanFactory的类层次结构如下:
在这里插入图片描述
DefaultListableBeanFactory其实要实现的功能就是以list集合的方式操作bean,为什么要拆成这么多的类和接口呢。这里面可能基于几点考虑。

1、功能的不同维度,分不同的接口,方便以后的维护和其他人的阅读。如:AutowireCapableBeanFactory、ListableBeanFactory、HierarchicalBeanFactory等
2、不同接口的实现,分布在不同的之类里,方便以后不同接口多种实现的扩展
3、从整个类图的分布,可以看出spring在这块是面向接口编程,后面类的实现,他们认为只是接口功能实现的一种,随时可以拓展成多种实现

通过名字就大概可以了解每个接口的功能:

HierarchicalBeanFactory接口是在继承BeanFactory的基础上,实现BeanFactory的父子关系。

AutowireCapableBeanFactory接口是在继承BeanFactory的基础上,实现Bean的自动装配功能

ListableBeanFactory接口是在继承BeanFactory的基础上,实现Bean的list集合操作功能

ConfigurableBeanFactory接口是在继承HierarchicalBeanFactory的基础上,实现BeanFactory的全部配置管理功能,

SingletonBeanRegistry是单例bean的注册接口
ConfigurableListableBeanFactory接口是继承AutowireCapableBeanFactory,ListableBeanFactory,ConfigurableBeanFactory三个接口的一个综合接口

AliasRegistry接口是别名注册接口,SimpleAliasRegistry类是简单的实现别名注册接口的类

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值