Skip to content

<font style="color:rgb(51, 51, 51);">Spring</font>

<font style="color:rgb(51, 51, 51);">Spring</font><font style="color:rgb(51, 51, 51);">Bean</font>

<font style="color:rgb(51, 51, 51);">Spring</font><font style="color:rgb(51, 51, 51);">BeanFactory</font><font style="color:rgb(51, 51, 51);">ApplicationContext</font>**<font style="color:rgb(51, 51, 51);">ApplicationContext</font>**

  1. <font style="color:rgb(51, 51, 51);">@ComponentScan</font>
  2. ````

首先解决给定一个包名,如何获取该包下的所有类的问题;

基本思路就是文件扫描,将文件路径拼接为类名,比如:com.example.hello

2025年1月2日15:40:34

❓但对于源码中 classLoader.getResource()等内容不是特别理解

目前的理解就是 classLoader 会去扫描环境变量中 classPath 路径下的包。

创建Bean Definition

画板

为要创建的 BeanBeanDefinition

java
public class BeanDefinition {
    // 全局唯一的Bean Name:
    String name;

    // Bean的声明类型:
    Class<?> beanClass;

    // Bean的实例:
    Object instance = null;

    // 构造方法/null:
    Constructor<?> constructor;

    // 工厂方法名称/null:
    String factoryName;

    // 工厂方法/null:
    Method factoryMethod;

    // Bean的顺序:
    int order;

    // 是否标识@Primary:
    boolean primary;

    // init/destroy方法名称:
    String initMethodName;
    String destroyMethodName;

    // init/destroy方法:
    Method initMethod;
    Method destroyMethod;
}

创建Bean实例

本部分主要解决的是在有了 beanDefination,如何创建 bean:

首先我们来看看spring 中支持的四种依赖注入的方式:

  1. 构造方法注入
  2. 工厂方法注入
  3. setter 方法注入
  4. 字段注入

在这里,构造方法注入和工厂方法注入,Bean的创建与注入是一体的,而后两种方式,即setter方法注入和属性注入,Bean的创建与注入是可以分开的,即先创建Bean实例,再用反射调用方法或字段,完成注入。

我们把前两种方式称为强依赖,后两种方式称为弱依赖

再来看看循环依赖的问题,Spring ioc 可以解决部分循环依赖的问题,但对于对于强依赖的循环依赖,是无法处理的,因为我们自己写 java 代码也无法处理这种情况,比如下边代码所示情况:

java
class A {
    final B b;
    A(B b) { this.b = b; }
}

class B {
    final A a;
    B(A a) { this.a = a; }
}

所以,对于IoC容器来说,创建Bean的过程分两步:

  1. 创建Bean的实例,此时必须注入强依赖;
  2. 对Bean实例进行Setter方法注入和字段注入。

第一步如果遇到循环依赖则直接报错,第二步则不需要关心有没有循环依赖(已经创建出 Bean 实例的话,那肯定可以解决循环依赖的问题)。

首先,我们先完成强依赖类型的 bean 的创建:

那么,创建 bean 实例的主要流程如下,这里先创建 Configuration 类型的 bean,再去创建普通 bean。因为 Configuration 标注的 bean 实际上是工厂 bean,内部通过 实例方法创建其他的 bean,所以必须先对他们进行实例化;

java
public AnnotationConfigApplicationContext(Class<?> configClass, PropertyResolver propertyResolver) {
    this.propertyResolver = propertyResolver;
    // 扫描获取所有Bean的Class类型:
    final Set<String> beanClassNames = scanForClassNames(configClass);
    // 创建Bean的定义:
    this.beans = createBeanDefinitions(beanClassNames);

    // 创建BeanName检测循环依赖:
    this.creatingBeanNames = new HashSet<>();

    // 创建@Configuration类型的Bean:
    this.beans.values().stream()
    // 过滤出@Configuration:
    .filter(this::isConfigurationDefinition).sorted().map(def -> {
        createBeanAsEarlySingleton(def);
        return def.getName();
    }).collect(Collectors.toList());

    // 创建其他普通Bean:
    List<BeanDefinition> defs = this.beans.values().stream()
            // 过滤出instance==null的BeanDefinition:
            .filter(def -> def.getInstance() == null)
            .sorted().collect(Collectors.toList());
    // 依次创建Bean实例:
    defs.forEach(def -> {
        // 如果Bean未被创建(可能在其他Bean的构造方法注入前被创建):
        if (def.getInstance() == null) {
            // 创建Bean:
            createBeanAsEarlySingleton(def);
        }
    });
}

剩下的工作,就是将createBeanAsEarlySingleton()

java
public Object createBeanAsEarlySingleton(BeanDefinition def) {
    // 检测循环依赖:
    if (!this.creatingBeanNames.add(def.getName())) {
        throw new UnsatisfiedDependencyException();
    }

    // 创建方式:构造方法或工厂方法:
    Executable createFn = def.getFactoryName() == null ?
        def.getConstructor() : def.getFactoryMethod();

    // 创建参数:
    Parameter[] parameters = createFn.getParameters();
    Object[] args = new Object[parameters.length];
    for (int i = 0; i < parameters.length; i++) {
        // 从参数获取@Value和@Autowired:
        Value value = ...
        Autowired autowired = ...
        // 检查Value和Autowired
        ...
        // 参数类型:
        Class<?> type = param.getType();
        if (value != null) {
            // 参数设置为查询的@Value:
            args[i] = this.propertyResolver.getRequiredProperty(value.value(), type);
        } else {
            // 参数是@Autowired,查找依赖的BeanDefinition:
            BeanDefinition dependsOnDef = name.isEmpty() ? findBeanDefinition(type) : findBeanDefinition(name, type);
            // 获取依赖Bean的实例:
            Object autowiredBeanInstance = dependsOnDef.getInstance();
            if (autowiredBeanInstance == null) {
                // 当前依赖Bean尚未初始化,递归调用初始化该依赖Bean:
                autowiredBeanInstance = createBeanAsEarlySingleton(dependsOnDef);
            }
            // 参数设置为依赖的Bean实例:
            args[i] = autowiredBeanInstance;
        }
    }
    // 已拿到所有方法参数,创建Bean实例:
    Object instance = ...
    // 设置实例到BeanDefinition:
    def.setInstance(instance);
    // 返回实例:
    return def.getInstance();
}

完成了强依赖类型 bean 的创建,下一步是完成****

`@Value``@Autowired`
java
public AnnotationConfigApplicationContext(Class<?> configClass, PropertyResolver propertyResolver) {
    ...

    // 通过字段和set方法注入依赖:
    this.beans.values().forEach(def -> {
        injectBean(def);
    });

    // 调用init方法:
    this.beans.values().forEach(def -> {
        initBean(def);
    });
}

Aop

首先实现AOP需要用户提供的两个Bean:

  1. 原始Bean,即需要被代理的Bean;
  2. 拦截器,即拦截了目标Bean的方法后,会自动调用拦截器实现代理功能。

注:本教程实现的AOP的API与Spring

https://pdai.tech/md/spring/spring-x-framework-aop.html

框架层面需要实现的:

  • ProxyResolver 创建AOP代理的工具类;
  • AroundProxyBeanPostProcessor 核心AOP实现逻辑,实现查找Bean、创建AOP代理类等逻辑;