微热山丘,探索 IoC、AOP 实现原理(一) IoC 实现原理

一. 简介及项目设定

1.1 微热山丘 介绍

warmhill(微热山丘)是一个参考 Spring 实现 IoC、AOP 特性的小项目。

相比于 Spring 庞杂的分类、层层继承、抽象,warmhill(微热山丘) 里都是简单直接的类、方法调用,核心在于简洁地展现实现原理。

1.2 项目设定及限制

有如下的限定:
1. 所有的 bean 都是单例。
2. bean 只有一个唯一的标识符 id,没有名字、别名。
3. 所有的 bean 都是立即初始化的,不支持延迟初始化。
4. 对于 BeanPostProcessor 的应用是基于声明的先后顺序。
5. 对于 AOP 的切入点,只支持对方法调用的拦截,不细分 Before/After/Around/Throw 等。
6. 对于 AOP 的配置也是基于 bean 定义的,不支持 <aop:config> 标签。
7. 目前只支持从 XML 方式配置 bean 。
8. bean 的属性目前只支持 String 类型和对其他 bean 的引用,只支持 setter 方法的依赖注入。

二. IoC、AOP 基本概念介绍

  • Resource: 资源。可存放在任意位置,只有一个方法: InputStream getStream();

  • BeanDefinition: bean 的定义信息。

  • BeanDefitionLoader: bean 定义加载类,只有一个方法: List<BeanDefinition> load();

  • BeanFactory: bean 工厂,负责根据 bean 定义创建 bean 的实例。

/**
 * 获取指定 bean 。
 * @param beanId beanId
 * @param <T> 目标 bean 类型
 * @return bean 实例
 */
<T> T getBean(String beanId);

/**
 * 获取实现了指定类型的所有 Bean 实例。
 * @param requiredType 目标 bean 类型
 * @param <T> 目标 bean 类型
 * @return 实现了指定类型的 bean 实例列表
 */
<T> List<T> getBeans(Class<T> requiredType);
  • BeanPostProcessor: 在 bean 的创建过程中对实例进行加工,以透明地添加额外的特性,AOP 就是通过这个机制实现的,事务控制是 AOP 的一个典型应用场景。
Object postProcessBeforInit(Object bean, String beanId);

Object postProcessAfterInit(Object bean, String beanId);
  • ApplicationContext: 应用上下文,继承了 BeanFactory 。职责:
  1. 根据应用提供的资源信息创建 Resource, 用 BeanDefitionLoader 加载 bean 定义,并注册到 BeanFactory 的实现类。
  2. 管理应用的生命周期,可以重新加载 bean 。

三. IoC 实现要点

IoC 的核心是由 bean 容器创建 bean,并注入 bean 的依赖对象。* AbstractBeanFactory bean 工厂实现的核心。

3.1 AbstractBeanFactory 的主要属性

  • List<String> beanIds 属性维护 bean 的声明顺序;
  • Map<String, BeanDefinition> definitionMap 提升根据 beanId 获取 bean 实例的效率。
  • List<BeanPostProcessor> processors 容器里所有的 BeanPostProcessor 实现。

3.2 bean 容器初始化的核心流程

  1. 创建所有的 BeanPostProcessor 实例,以便对后续其他 bean 创建过程进行介入处理。
  2. 创建其他的 bean 实例,所有 bean 的创建过程中都会应用也有的 BeanPostProcessor 实例。
    > 2.1 创建原始类型的实例;
    > 2.2 注入依赖的属性;
    > 2.3 对原始类型的实例逐个应用 BeanPostProcessor,返回加工后的对公;
    > 2.4 把加工后的对象注册到容器里。

代码如下:

// 触发所有 bean 创建的方法
public void refresh() {
    // 创建所有的 BeanPostProcessor 实例
    initBeanpostProcess();

    // 创建其他的 bean 实例
    initRemain();
}

private void initRemain() {
    beanIds.forEach(beanId -> getBean(beanId));
}

private void initBeanpostProcess() {
    processors = getBeans(BeanPostProcessor.class);
}

@Override
public <T> T getBean(String beanId) {
    BeanDefinition bdf = definitionMap.get(beanId);
    Object bean = bdf.getBean();
    if (bean == null) {
        // 1. 创建原始类型的实例
        bean = createBean(bdf);

        // 2. 注入依赖的属性
        applyProperties(bean, bdf.getPropertyValues());

        // 3. 加工
        bean = processBean(bean, bdf);

        // 4. 作为最终的结果 bean 
        bdf.setBean(bean);
    }
    return (T) bean;
}

protected void applyProperties(Object bean, PropertyValues propertyValues) {
}

// 对原始的 bean 实例进行加工,返回加工后的对象
private Object processBean(Object bean, BeanDefinition bdf) {
    for (BeanPostProcessor beanPostProcessor : processors) {
        bean = beanPostProcessor.postProcessBeforInit(bean, bdf.getBeanId());
    }

    // TODO 调用 bean 的初始化方法。

    for (BeanPostProcessor beanPostProcessor : processors) {
        bean = beanPostProcessor.postProcessAfterInit(bean, bdf.getBeanId());
    }

    return bean;
}

// 创建原始的 bean 实例
protected Object createBean(BeanDefinition bdf) {
    try {
        Object o = bdf.getType().newInstance();
        return o;
    } catch (InstantiationException | IllegalAccessException e) {
        throw new BeanCreationException("create bean of " + bdf.getType() + " error .", e);
    }
}

/**
 * 获取实现了给定类型的所有 bean 实例。
 *
 * @param requiredType 目标 bean 类型
 * @param <T>
 * @return 满足条件的实例列表
 */
@Override
public <T> List<T> getBeans(Class<T> requiredType) {
    // 按 bean 的声明顺序获取实例
    List<Object> beans = beanIds.stream()
            .map(beanId -> definitionMap.get(beanId))
            .filter(bdf -> requiredType.isAssignableFrom(bdf.getType()))
            .map(bdf -> getBean(bdf.getBeanId()))
            .collect(Collectors.toList());
    return (List<T>) beans;
}

3.3 依赖注入

依赖注入是在 AutoCapableBeanFactory 类完成。

@Override
protected void applyProperties(Object bean, PropertyValues propertyValues) {
    // 如果 bean 类型实现了对工厂的监听,则注入工厂实例。
    if (BeanFactoryAware.class.isAssignableFrom(bean.getClass())) {
        ((BeanFactoryAware) bean).setBeanFactory(this);
    }

    for (PropertyValue propertyValue : propertyValues.getList()) {
        String name = propertyValue.getName();
        Object value = propertyValue.getValue();
        if (value instanceof BeanReference) {
            value = getBean(((BeanReference) value).getBeanId());
        }

        String setter = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
        try {
            Method setMethod = bean.getClass().getDeclaredMethod(setter, value.getClass());
            setMethod.setAccessible(true);
            setMethod.invoke(bean, value);

        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            try {
                Field field = bean.getClass().getDeclaredField(name);
                field.setAccessible(true);
                field.set(bean, value);
            } catch (NoSuchFieldException | IllegalAccessException e1) {
                throw new BeanCreationException("set property " + name + " error");
            }
        }
    }
}

3.4 构建完整的上下文

应用上下文的两大核心职责:

  • 从给定资源加载 bean 定义。
  • 用 bean 定义构建 bean 容器工厂。

ClasspathApplicationContext 类:

// 1. 创建一个 类路径下的资源
ClasspathResources resources = new ClasspathResources(xmlPath);

// 2. 创建一个 bean 定义加载器并加装 bean 定义
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(resources);
List<BeanDefinition> definitionList = beanDefinitionReader.load();

// 3. 创建 bean 工厂、注册 bean 定义、初始化所有的 bean
AutoCapableBeanFactory beanFactory = new AutoCapableBeanFactory();
definitionList.forEach(beanDefinition -> beanFactory.registerBeanDefinition(beanDefinition));
beanFactory.refresh();

欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据