Spring IOC实现主要过程

本文针对的是icomac-spring项目,是自己重现了tianxiaono的仿写toy-spring项目,最开始的版本是黄亿华前辈实现的 tiny-spring ,该项目时间节点是 2014.1

具体参考:自己动手实现的 Spring IOC 和 AOP - 下篇

xml 的解析

BeanFactory 初始化时,会根据传入的 xml 配置文件路径加载并解析配置文件。但是加载和解析 xml 配置文件这种脏活累活,BeanFactory 可不太愿意干,它只想高冷的管理容器中的 bean。于是 BeanFactory 将加载和解析配置文件的任务委托给专职人员 BeanDefinitionReader 的实现类 XmlBeanDefinitionReader 去做。那么 XmlBeanDefinitionReader 具体是怎么做的呢?XmlBeanDefinitionReader 做了如下几件事情:

  1. 将 xml 配置文件加载到内存中
  2. 获取根标签下所有的标签
  3. 遍历获取到的标签列表,并从标签中读取 id,class 属性
  4. 创建 BeanDefinition 对象,并将刚刚读取到的 id,class 属性值保存到对象中
  5. 遍历标签下的标签,从中读取属性值,并保持在 BeanDefinition 对象中
  6. 将 <id, BeanDefinition> 键值对缓存在 Map 中,留作后用
  7. 重复3、4、5、6步,直至解析结束

BeanFactory

BeanFactory 的生命流程,也就是 IOC 容器的生命流程

  1. BeanFactory 加载 Bean 配置文件,将读到的 Bean 配置封装成 BeanDefinition 对象
  2. 将封装好的 BeanDefinition 对象注册到 BeanDefinition 容器中
  3. 注册 BeanPostProcessor 相关实现类到 BeanPostProcessor 容器中
  4. BeanFactory 进入就绪状态
  5. 外部调用 BeanFactory 的 getBean(String name) 方法,BeanFactory 着手实例化相应的 bean
  6. 重复步骤 3 和 4,直至程序退出,BeanFactory 被销毁

注册BeanPostProcessor

XmlBeanDefinitionReader 在完成解析工作后,BeanFactory 会将它解析得到的 <id, BeanDefinition> 键值对注册到自己的 beanDefinitionMap 中。

BeanFactory 注册好 BeanDefinition 后,就立即开始注册 BeanPostProcessor 相关实现类。这个过程比较简单:

  1. 根据 BeanDefinition 记录的信息,寻找所有实现了 BeanPostProcessor 接口的类。
  2. 实例化 BeanPostProcessor 接口的实现类
  3. 将实例化好的对象放入 List中
  4. 重复2、3步,直至所有的实现类完成注册

getBean 过程解析

在完成了 xml 的解析、BeanDefinition 的注册以及 BeanPostProcessor 的注册过程后。BeanFactory 初始化的工作算是结束了,此时 BeanFactory 处于就绪状态,等待外部程序的调用。

外部程序一般都是通过调用 BeanFactory 的 getBean(String name) 方法来获取容器中的 bean。BeanFactory 具有延迟实例化 bean 的特性,也就是等外部程序需要的时候,才实例化相关的 bean。这样做的好处是比较显而易见的,第一是提高了 BeanFactory 的初始化速度,第二是节省了内存资源。

  1. 实例化bean对象
  2. 设置对象属性
  3. 检查Aware相关接口并设置相关依赖
  4. BeanPostProcessor前置处理
  5. 检查是否是InitializingBean以决定是否调用afterPropertiesSet方法
  6. 检查是否配置有自定义的init-method
  7. BeanPostProcessor后置处理
  8. 注册必要的Destruction相关回调接口
  9. 使用中
  10. 是否实现DisposableBean接口
  11. 是否配置有自定义的destroy方法

对于icomac-spring项目

  1. 实例化 bean 对象,类似于 new XXObject()
  2. 将配置文件中配置的属性填充到刚刚创建的 bean 对象中
  3. 检查 bean 对象是否实现了 Aware 一类的接口,如果实现了则把相应的依赖设置到 bean 对象中。icomac-spring 目前仅对 BeanFactoryAware 接口实现类提供了支持
  4. 调用 BeanPostProcessor 前置处理方法,即 postProcessBeforeInitialization(Object bean, String beanName)
  5. 调用 BeanPostProcessor 后置处理方法,即 postProcessAfterInitialization(Object bean, String beanName)
  6. bean 对象处于就绪状态,可以使用了

测试类 

package com.icomac.spring.ioc;

import com.icomac.spring.Car;
import com.icomac.spring.HelloService;
import com.icomac.spring.Wheel;
import com.icomac.spring.ioc.xml.XmlBeanFactory;

import org.junit.Test;

/**
 * Created by icomac on 19/4/10.
 */
public class XmlBeanFactoryTest {

    @Testd
    public void getBean() throws Exception {
        System.out.println("--------- IOC test ----------");
        String location = getClass().getClassLoader().getResource("toy-spring.xml").getFile();
        XmlBeanFactory bf = new XmlBeanFactory(location);
        Wheel wheel = (Wheel) bf.getBean("wheel");
        System.out.println(wheel);
        Car car = (Car) bf.getBean("car");
        System.out.println(car);
    }
}

最后结果

猜你喜欢

转载自blog.csdn.net/sinat_33801679/article/details/89193716