动手实现复杂的springioc

IOC的实现

BeanFactory的生命流程
1、XmlBeanFactory类通过XmlBeanDefinitionReader的loadBeanDefinition方法将xml进行解析,将读取到的bean配置封装成BeanDefinition 对象
2、将封装好的BeanDefinition 对象注册到BeanDefinition 容器中
3、注册BeanPostProcessor相关实现类到BeanPostProcessor容器中
4、XmlBeanFactory进行就绪状态
5、外部调用XmlBeanFactory的getBean方法,XmlBeanFactory着手实例化相应的bean
6、重复步骤3和4,直至程序退出,XmlBeanFactory别销毁
BeanDefinition 及其他一些类的介绍
在这里插入图片描述
1、BeanDefinition,从字面意思上翻译成中文就是 “Bean 的定义”。从翻译结果中就可以猜出这个类的用途,即根据 Bean 配置信息生成相应的 Bean 详情对象。
2、BeanReference 对象保存的是 bean 配置中 ref 属性对应的值,在后续 BeanFactory 实例化 bean 时,会根据 BeanReference 保存的值去实例化 bean 所依赖的其他 bean。
3、PropertyValues 和 PropertyValue 这两个长的比较像的类,首先是PropertyValue。PropertyValue 中有两个字段 name 和 value,用于记录 bean 配置中的标签的属性值。然后是PropertyValues,PropertyValues 从字面意思上来看,是 PropertyValue 复数形式,在功能上等同于 List。
XmlBeanDefinitionReader进行XML解析
1、BeanFactory初始化时,会根据传入的xml配置文件路径加载并解析配置文件。但是加载和解析这种脏活累活,BeanFactory不会干,它只想管理容器中的bean。于是BeanFactory将加载和解析配置文件的任务交给 BeanDefinitionReader 的实现类 XmlBeanDefinitionReader 去做。
1、将xml配置文件加载到内存中
2、获取根标签下的所有标签
3、遍历获取到的标签列表,并从标签中读取id,class属性
4、创建BeanDefinition对象,将刚刚读取到的id,class属性保存到对象中
5、遍历标签下的标签,从中获取属性值,并保存在BeanDefinition对象的PropertyValues中
6、将<id,BeanDefinition>键值对缓存在Map中,留作后用
7、重复3、4、5、6步,直至解析结束
注册 BeanPostProcessor
BeanPostProcessor 接口是 Spring 对外拓展的接口之一,其主要用途提供一个机会,让开发人员能够插手 bean 的实例化过程。通过实现这个接口,我们就可在 bean 实例化时,对bean 进行一些处理。比如,我们所熟悉的 AOP 就是在这里将切面逻辑织入相关 bean 中的。正是因为有了 BeanPostProcessor 接口作为桥梁,才使得 AOP 可以和 IOC 容器产生联系。关于这一点,我将会在后续章节详细说明。
接下来说说 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。

@Override
    public Object getBean(String name) throws Exception {
        BeanDefinition beanDefinition=beanDefinitionMap.get(name);
        if (beanDefinition==null){
            throw new IllegalArgumentException("no this bean with name "+name);
        }
        Object bean=beanDefinition.getBean();
        if (bean==null){
            bean=createBean(beanDefinition);
            bean=initializeBean(bean,name);
            beanDefinition.setBean(bean);
        }
        return bean;
    }

这样做的好处时比较显而易见的,第一时提高了BeanFactory的初始化速度,第二是节省了内存资源。bean的实例化过程:
在这里插入图片描述
上图是一个完整的实例化过程图,在仿写项目中,流程如下:
在这里插入图片描述
1、实例化bean对象,类似于new xxObject();
2、将配置文件中的属性填充到刚刚创建的bean对象中
3、检查bean对象是否实现了 Aware 一类的接口,如果实现了则把相应的依赖设置到 bean 对象中。toy-spring 目前仅对 BeanFactoryAware 接口实现类提供了支持
4、调用 BeanPostProcessor 前置处理方法,即 postProcessBeforeInitialization(Object bean, String beanName)
5、调用 BeanPostProcessor 后置处理方法,即 postProcessAfterInitialization(Object bean, String beanName)
6、bean 对象处于就绪状态,可以使用了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值