2.自动创建bean对象

🤔 2.自动创建bean对象

本节中主要是以上一节为基础,并对上一节制作的IOC容器进行改良,上一节中,bean对象的实例化是手动new出来的,这一节中将bean对象的创建交给IOC容器本身,并且为了考虑扩展性,尽可能的使得每一个类都只执行一个职责,最终让整个项目变得更加健壮,本节中创建的bean默认单例。关于项目的源码存放在 仓库

思路

本节就是在上一节的基础上将bean的创建交给了IOC容器,并且实现了一个单例模式(默认)的bean,具体的设计图如下:

img

可以看出,只是在定义、注册、获取的基础上多了几个模块,例如获取bean对象的时候要判断是否已经存在,存在直接返回,不存在就创建再返回等。。。项目的核心类图如下:

image-20231030100215419

下面依次针对每一个类进行讲解

类的说明

  1. SingletonBeanRegistry:是一个接口,只是提供了一个待实现的getSingleton(String beanName)方法,后期获取bean对象时调用getBean方法,内部调用这个方法,尝试获取一个单例模式的bean,方法的实现在DefaultSingletonBeanRegistry类中,主要就是从容器中按照bean对象的名称尝试获取bean对象,对象不存在返回值为null

    image-20231030101148658

  2. DefaultSingletonBeanRegistry:是SingletonBeanRegistry的实现类,类中有如下方法:

    image-20231030101229608

    内部有一个名为singletonObjects的HashMap容器,主要存储已经实例化后的bean对象及其名称之间的映射关系,主要实现了getSingleton(String beanName)方法,并且还增加了一个addSingleton(String beanName, Object singletonObject)方法,主要作用是对外提供一个保存实例化后的bean对象的api,在AbstractAutowireCapableBeanFactory类中的createBean(String beanName, BeanDefinition beanDefinition)中使用,主要作用是将利用反射创建的bean对象保存到容器中,使的bean变成单例

  3. BeanFactory:是一个接口,提供了一个待实现的getBean(String name)方法,对外暴露之后,可以实现从IOC容器中尝试获取一个单例模式的bean对象

    image-20231030101242268

  4. AbstractBeanFactory:继承了DefaultSingletonBeanRegistry类,实现了BeanFactory接口,类中现有如下方法:

    image-20231030102023153

    主要是实现了getBean(String name)方法,根据名称尝试获取实例化之后的 bean对象,内部调用继承的getSingleton方法尝试获取一个单例模式的bean对象。不存在的话就调用继承的createBean方法创建并返回一个bean对象,也就是先调用,不存在就创建

  5. AbstractAutowireCapableBeanFactory:主要是将继承下来的createBean(String beanName, BeanDefinition beanDefinition)方法实现了,内部使用反射机制从BeanDefinition中取出bean的类信息从而利用反射创建一个实例对象(此时这个对象还没有属性),并且调用addSingleton方法将其保存到singletonObjects中,类的结构如下:

    image-20231030102532007

    需要注意的是,这里创建的是最简单的bean对象,无法在创建对象时传递参数,本项目只是实现了两个功能,一个是将bean的创建交给IOC容器,一个是创建的bean保证是单例模式的,后期会实现带参的对象构建,正常来说就实现创建无参的bean对象,然后进行属性填充

  6. BeanDefinitionRegistry:是一个接口,主要提供了一个待实现的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法,用来注册bean,也就是将bean的名称与其类信息绑定到一起,使用一个HashMap存储,实现类在DefaultListableBeanFactory中,类的结构如下:

    image-20231030102733823

  7. DefaultListableBeanFactory:项目中最核心的一个类,通过一层一层的叠加,每一个类都实现自己的功能,然后在这个类中将其他所有的类的功能集成在一起,形成的类结构如下:

    image-20231030102957493

    所有的已实现的方法被集中到了这一个类中,外部直接通过这个类调用这些已实现的api即可,这就是项目结构中最底层类的好处,最底层类对外暴露,使得所有的方法都可以继承被使用

bean的创建和获取

​ 为了将bean的创建交给IOC容器,回想一下学过的知识,不手工new还能得到对象的方法就是反射,所以这里我们在注册时,也就是BeanDefinition时保存的不再是bean对象,而是一个类的信息,后期IOC容器可以通过这个类信息使用反射的知识来创建一个bean对象

​ 并且平时在使用spring框架搭建项目时,bean可以选择很多模式,比如singletonprototype,本节中就简单的实现单例模式的bean对象创建,为了实现单例模式,需要进行判断,当获取bean对象,对象不存在时,直接创建,并且底层需要将这个创建的bean对象保存到一个容器中,后期再次使用的时候,直接拿出这个已经创建过的对象,这样就不会反复的创建新的bean对象,从而实现单例模式,核心代码如下:

1
2
3
4
5
6
7
8
public Object getBean(String name) throws BeansException {
    Object bean = getSingleton(name);
    if (bean != null) {
        return bean;
    }
    BeanDefinition beanDefinition = getBeanDefinition(name);
    return createBean(name, beanDefinition);
}

bean存在时直接返回,不存在时创建了再返回

​ 需要注意的是,获取bean对象的时候,经历了如下的流程:

image-20231030114408629

并且创建bean的过程中,只创建了无参数的bean,一旦想要创建bean的时候让bean携带一些参数,就会出现异常,也就是说现在还无法创建带参数的bean,如何解决,看下一节!

总结

为了实现将bean的创建交给IOC容器,本项目做了如下几点工作:

  1. 注册bean的时候,保存的不再是实例化后的bean,而是bean的类信息,在需要的时候通过反射利用类信息创建一个实例即可
  2. 为了实现单例模式的bean创建,调用一些方法,存在就返回,不存在就创建,并且创建之后将实例化后的bean保存到一个容器中,后期随用随取
  3. 为了增强程序的健壮性,将单例模式的IOC容器的各个功能进行划分,每个类只做自己的事情,通过继承将这些方法得到,一层一层的逐步实现,最后最底层的类就集成了所有的方法,直接调用api就可以实现相应的功能

项目中的文件分为两类,一类是提供统一接口、模版或者全局都会使用的配置文件,一类是实现具体功能的支持文件,文件的主要结构如下:

image-20231030105730924

每个类只做自己的工作,将业务逻辑区分开,核心就是整体的类图,这个类图将整个项目的功能拆分开,每个类实现一个功能,最后将这些功能集成到同一个类中

本文只是做了两个工作:

  1. bean的创建交给IOC容器
  2. bean的创建保证是单例模式

下一节中将解决创建bean对象时无法创建携带参数的bean对象,也就是无法利用有参构造创建bean对象的问题