跳至主要內容

第03章:实现含构造函数的类实例化策略

AruNi_Lu框架Spring约 686 字大约 2 分钟

本文内容

1. 设计

在第02章的设计中,虽然扩充了 Bean 容器的功能,将类的实例化交给了容器来处理,但是并 没有考虑到带有有参构造器的类的实例化,因此这章我们来进行改造,使其具备获取有参 Bean 的能力。

具体的,在 BeanFactory 中添加 Object getBean(String name, Object... args) 接口,即可在获取 Bean 的时候把构造函数的入参信息传递进去,从而能实例化有参数的 Bean 对象。

另外,我们使用两种方式来创建含有构造函数的 Bean 对象,分别是基于 JDK 的方法 DeclaredConstructor() 和基于 Cglib 的 enhancer.create() 方法。

2. 实现

得利于之前的设计,现在我们只需要添加一个 实例化策略模块,供实例化对象的时候使用即可。

目录结构更新如下:

image-20230314082905201

类图如下:

step-04

  • InstantiationStrategy:实例化策略接口,提供一个实例化方法 instantiate(),入参包括 BeanDefinition、beanName、Class 的构造器、参数;
  • 提供两个 InstantiationStrategy 的实现类 SimpleInstantiationStrategyCglibSubclassingInstantiationStrategy,分别是基于 JDK 和基于 Cglib 的方式来实例化对象;
  • 在 AbstractBeanFactory 类中,使用 重载 机制,新增一个带有入参的 getBean() 方法。由于重载的方法有 2 个,都需要进行获取 Bean,所以抽取一个 doGetBean() 方法做具体的流程,供它们调用;
  • 在 AbstractAutowireCapableBeanFactory 类中,新增 createBeanInstance() 方法,用于 具体创建 Bean 实例
    1. 先通过 Class.getDeclaredConstructors() 获取 该 Class 的所有构造器
    2. 遍历所有构造器,将构造器的参数个数和类型与入参的参数做对比,选出需要的构造器
    3. 选出的构造器作为参数传递给实例化策略中的方法,进行具体的实例化。

3. 测试

先给测试 bean 的 UserService 添加一个遍历 String name,提供有参无参构造方法。

测试方法:

@Test
public void test_BeanFactory() {
    // 1. 初始化 BeanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //beanFactory.setInstantiationStrategy(new SimpleInstantiationStrategy());

    // 2. 注册 bean
    BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
    beanFactory.registerBeanDefinition("userService", beanDefinition);

    // 3. 带有参数的获取 bean
    UserService userService = (UserService) beanFactory.getBean("userService", "AruNi");
    userService.queryUserInfo();
    
    // 输出:查询用户信息:AruNi
}

4. 流程

整体流程如下:

上次编辑于: