Spring源码学习

第一章bean的元数据

一、bean的注入方式

  1. xml
<beah id="user" class="com. ydlclass.user" scope=" prototype" autowire="byType" init-method="init" depends-on="a,b" >
	<property name= "name" value="jerry"/>
	<property name="age" value="18"/>
</bean>
  1. 注解
@Controller
public class UserController{}
@Service
public class UserService{}
@Repository
public class UserService{}
@Compoment
public class UserService{}
  1. 配置类
@Configuration
public class UserConfiguration {
	@Bean("user")
	public User user(){
		User user = new user());
		user.setName("lily");
		user.setAge(20);
		return user;
	}
}
  1. import注解
public class MySelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.ydlclass.UserService", "com.ydlclass.UserDao"};
    }
}

@Configuration
@Import(MySelector.class)
public class UserConfiguration {}

二、BeanDefinition详解

bean存在多种不同的元数据,Spring在构造bean时,需要将千差万别的class概括成一种统一的描述性语言,Spring提供了一个接口BeanDefinition统一了这种描述bean的元数据。

一个BeanDefinition大概保存了以下信息:

  1. 定义了id、别名与Bean的对应关系(BeanDefinitionHolder)
  2. 具体的工厂方法(CIass类型),包括工厂方法的返回类型,工厂方法的Method对象
  3. 构造函数、构造函数形参类型
  4. Bean的class对象
  5. 作用范围、是否懒加载等等

  • BeanDefinition接口定义了一些基础的数据
  • AbstractBeanDefinition抽象类在接口上提供了一些基础的实现
  • 具体的实现类细化了方法的实现,提供了不同的解决方案
    (不同实现类事件的处理上采取不一样的策略,但都实现了同一个接口,这就是多态的表现)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * BeanDefinition 接口描述了 Spring 容器中的 Bean 的配置元数据。
 * 它定义了 bean 的属性、依赖关系、作用域以及生命周期方法。
 */
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
    
    // 常量定义 Bean 的作用域 - 单例
    String SCOPE_SINGLETON = "singleton";

    // 常量定义 Bean 的作用域 - 原型
    String SCOPE_PROTOTYPE = "prototype";

    // Bean 的角色 - 应用级别
    int ROLE_APPLICATION = 0;

    // Bean 的角色 - 支持类(如工具类)
    int ROLE_SUPPORT = 1;

    // Bean 的角色 - 基础设施类(框架内部使用)
    int ROLE_INFRASTRUCTURE = 2;

    // 设置父 Bean 的名称,用于 Bean 配置的继承
    void setParentName(@Nullable String parentName);

    // 获取父 Bean 的名称
    @Nullable
    String getParentName();

    // 设置该 Bean 的类名(全限定名)
    void setBeanClassName(@Nullable String beanClassName);

    // 获取该 Bean 的类名(全限定名)
    @Nullable
    String getBeanClassName();

    // 设置该 Bean 的作用域(如 singleton 或 prototype)
    void setScope(@Nullable String scope);

    // 获取该 Bean 的作用域
    @Nullable
    String getScope();

    // 设置该 Bean 是否懒加载(lazy-init),若为 true,Bean 将在首次使用时初始化
    void setLazyInit(boolean lazyInit);

    // 获取该 Bean 是否懒加载
    boolean isLazyInit();

    // 设置该 Bean 的依赖项,即必须在这些 Bean 初始化之后才能初始化此 Bean
    void setDependsOn(@Nullable String... dependsOn);

    // 获取该 Bean 的依赖项
    @Nullable
    String[] getDependsOn();

    // 设置该 Bean 是否为自动装配的候选者
    void setAutowireCandidate(boolean autowireCandidate);

    // 获取该 Bean 是否为自动装配的候选者
    boolean isAutowireCandidate();

    // 设置该 Bean 是否为主要的自动装配候选者(primary)
    void setPrimary(boolean primary);

    // 获取该 Bean 是否为主要的自动装配候选者
    boolean isPrimary();

    // 设置工厂 Bean 的名称,用于实例化该 Bean 的工厂类
    void setFactoryBeanName(@Nullable String factoryBeanName);

    // 获取工厂 Bean 的名称
    @Nullable
    String getFactoryBeanName();

    // 设置工厂方法的名称,使用工厂方法来创建该 Bean 实例
    void setFactoryMethodName(@Nullable String factoryMethodName);

    // 获取工厂方法的名称
    @Nullable
    String getFactoryMethodName();

    // 获取构造函数参数的值
    ConstructorArgumentValues getConstructorArgumentValues();

    // 检查是否有构造函数参数值
    default boolean hasConstructorArgumentValues() {
        return !this.getConstructorArgumentValues().isEmpty();
    }

    // 获取 Bean 的属性值,用于依赖注入
    MutablePropertyValues getPropertyValues();

    // 检查是否有属性值
    default boolean hasPropertyValues() {
        return !this.getPropertyValues().isEmpty();
    }

    // 设置初始化方法的名称,该方法将在 Bean 完成初始化时调用
    void setInitMethodName(@Nullable String initMethodName);

    // 获取初始化方法的名称
    @Nullable
    String getInitMethodName();

    // 设置销毁方法的名称,该方法将在 Bean 被销毁时调用
    void setDestroyMethodName(@Nullable String destroyMethodName);

    // 获取销毁方法的名称
    @Nullable
    String getDestroyMethodName();

    // 设置 Bean 的角色(应用、支持或基础设施)
    void setRole(int role);

    // 获取 Bean 的角色
    int getRole();

    // 设置 Bean 的描述信息
    void setDescription(@Nullable String description);

    // 获取 Bean 的描述信息
    @Nullable
    String getDescription();

    // 获取该 Bean 的可解析类型(用于泛型处理)
    ResolvableType getResolvableType();

    // 判断该 Bean 是否为单例作用域
    boolean isSingleton();

    // 判断该 Bean 是否为原型作用域
    boolean isPrototype();

    // 判断该 Bean 是否为抽象类,抽象 Bean 不能实例化
    boolean isAbstract();

    // 获取该 Bean 定义的资源描述(例如 XML 文件的位置)
    @Nullable
    String getResourceDescription();

    // 获取原始的 BeanDefinition(例如通过继承生成的 BeanDefinition)
    @Nullable
    BeanDefinition getOriginatingBeanDefinition();
}

GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition异同:
GenericBeanDefinitionRootBeanDefinitionChildBeanDefinition 是 Spring 框架中常见的三种 BeanDefinition 实现

  • GenericBeanDefinition 是 Spring 3.0 引入的一个通用 Bean 定义类,它没有附加的约束,几乎可以替代 RootBeanDefinitionChildBeanDefinition
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyService.class);
beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
  • RootBeanDefinition 是早期 Spring 版本中常用的 BeanDefinition 实现之一,通常用于定义独立的 Bean,也就是没有父 Bean的 Bean。
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(MyService.class);
rootBeanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
  • ChildBeanDefinition 是用于定义子 Bean 的 BeanDefinition 实现,允许继承其他 Bean 的配置。
ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("parentBean");
childBeanDefinition.getPropertyValues().add("propertyName", "value");

三、BeanDefinition注册器

有了统一的标准的元数据后,我们可以进行统一的管理,此时需要一个容器去存储。

可以使用map这样的集合类,当然spring差不多是这么做的,它提供了一个接口BeanDefinitionRegistry

只要实现了这个接口,就会有注册BeanDefinition的能力。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.beans.factory.support;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.AliasRegistry;

/**
 * BeanDefinitionRegistry 是 Spring 中 Bean 定义注册的核心接口,
 * 它允许在 Spring 容器中注册、移除和获取 BeanDefinition。
 * 这个接口扩展了 AliasRegistry,用于处理 Bean 的别名。
 */
public interface BeanDefinitionRegistry extends AliasRegistry {

    /**
     * 注册给定名称的 BeanDefinition。
     *
     * @param beanName       Bean 的名称
     * @param beanDefinition 要注册的 BeanDefinition
     * @throws BeanDefinitionStoreException 如果 BeanDefinition 无法存储
     */
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;

    /**
     * 移除给定名称的 BeanDefinition。
     *
     * @param beanName 要移除的 Bean 的名称
     * @throws NoSuchBeanDefinitionException 如果找不到指定的 BeanDefinition
     */
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 根据名称获取 BeanDefinition。
     *
     * @param beanName Bean 的名称
     * @return 指定名称的 BeanDefinition
     * @throws NoSuchBeanDefinitionException 如果找不到指定的 BeanDefinition
     */
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 检查是否包含给定名称的 BeanDefinition。
     *
     * @param beanName 要检查的 Bean 名称
     * @return 如果包含 BeanDefinition 则返回 true,否则返回 false
     */
    boolean containsBeanDefinition(String beanName);

    /**
     * 获取所有已注册的 BeanDefinition 名称。
     *
     * @return 所有 BeanDefinition 名称的数组
     */
    String[] getBeanDefinitionNames();

    /**
     * 获取已注册的 BeanDefinition 总数。
     *
     * @return BeanDefinition 的数量
     */
    int getBeanDefinitionCount();

    /**
     * 检查给定名称的 BeanDefinition 是否可以被覆盖。
     *
     * @param beanName 要检查的 Bean 名称
     * @return 默认返回 true,表示可以被覆盖
     */
    default boolean isBeanDefinitionOverridable(String beanName) {
        return true;
    }

    /**
     * 检查给定的 Bean 名称是否正在使用中(包括别名和实际 Bean 名称)。
     *
     * @param beanName 要检查的 Bean 名称
     * @return 如果名称正在使用中则返回 true,否则返回 false
     */
    boolean isBeanNameInUse(String beanName);
}

SimpleBeanDefinitionRegistry为例子,看其源码:

package org.springframework.beans.factory.support;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.SimpleAliasRegistry;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

// SimpleBeanDefinitionRegistry 类实现了 BeanDefinitionRegistry 接口,
// 用于注册和管理 BeanDefinition。
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
    // 存储 BeanDefinition 的映射,使用线程安全的 ConcurrentHashMap。
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);

    // 构造函数
    public SimpleBeanDefinitionRegistry() {
    }

    // 注册 BeanDefinition,使用指定的 beanName 和 BeanDefinition。
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        // 确保 beanName 非空
        Assert.hasText(beanName, "'beanName' must not be empty");
        // 确保 beanDefinition 不为空
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        // 将 BeanDefinition 存入 map
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    // 移除指定名称的 BeanDefinition。
    public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        // 尝试从 map 中移除 beanDefinition,若未找到则抛出异常
        if (this.beanDefinitionMap.remove(beanName) == null) {
            throw new NoSuchBeanDefinitionException(beanName);
        }
    }

    // 获取指定名称的 BeanDefinition。
    public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        // 从 map 中获取 BeanDefinition
        BeanDefinition bd = this.beanDefinitionMap.get(beanName);
        // 若未找到,抛出异常
        if (bd == null) {
            throw new NoSuchBeanDefinitionException(beanName);
        } else {
            return bd;
        }
    }

    // 检查是否包含指定名称的 BeanDefinition。
    public boolean containsBeanDefinition(String beanName) {
        return this.beanDefinitionMap.containsKey(beanName);
    }

    // 获取所有注册的 BeanDefinition 名称。
    public String[] getBeanDefinitionNames() {
        return StringUtils.toStringArray(this.beanDefinitionMap.keySet());
    }

    // 获取当前注册的 BeanDefinition 的数量。
    public int getBeanDefinitionCount() {
        return this.beanDefinitionMap.size();
    }

    // 检查给定的 beanName 是否正在使用(即是否是别名或存在的 BeanDefinition)。
    public boolean isBeanNameInUse(String beanName) {
        return this.isAlias(beanName) || this.containsBeanDefinition(beanName);
    }
}

SimpleBeanDefinitionRegistry使用了ConcurrentHashMap当作容器,对bean进行简单的管理

构造器的使用:

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.*;

public class SimpleBeanDefinitionRegistryExample {
    public static void main(String[] args) {
        // 创建 SimpleBeanDefinitionRegistry 实例
        SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();

        // 创建 BeanDefinition
        BeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);

        // 注册 BeanDefinition
        registry.registerBeanDefinition("myBean", beanDefinition);

    }
}

// 示例 Bean 类
class MyBean {
    // Bean 的属性和方法
}

四、加载BeanDefinition

  1. 读取xml配置文件
// 定义一个注册器,用来注册和管理 BeanDefinition 
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); 
// 通过 XML 文件加载 
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(registry);
//加载xml文件,将bean注册到注册器中
xmlReader.loadBeanDefinitions("classpath:spring.xml");
  1. 加载带注解的Bean
// 定义一个注册器,用来注册和管理 BeanDefinition 
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); 
// 通过注解加载 
AnnotatedBeanDefinitionReader annoReader = new AnnotatedBeanDefinitionReader(registry); 
// 注册 User 类 
annoReader.register(User.class);
  1. 读取配置类
    ConfigurationClassBeanDefinitionReader 是 Spring 框架内部用于处理配置类的一个类,它负责读取带有 @Configuration 注解的类并注册其定义的 Bean。
  2. 类路径扫描
// 定义一个注册器,用来注册和管理 BeanDefinition
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();

// 通过扫描包的方式
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry);
scanner.scan("com.ydlclass");

五、包扫描源码

解析一个类的方式:

  • 加载一个类到内存,获取Class对象,通过反射获取元数据
  • 直接操纵字节码文件(.class),读取字节码内的元数据

spring选择的是第二种

  • 第二种性能要优于第一种,省略类加载的过程
  • 第一种会将扫描的类全部都加载到堆内存,会浪费空间,增加gc次数,第二种可以根据元数据按需加载
  1. 类加载和内存使用
  • 反射方式(第一种方式)
    反射依赖于 JVM 将类加载到内存中,必须首先通过 ClassLoader 将类的 .class 文件加载到堆内存。这意味着每个被解析的类都需要被 JVM 加载,并且占用内存。当你解析大量类时,所有这些类对象都会驻留在内存中,导致内存使用增加,垃圾回收(GC)次数和频率可能会增加。
  • 缺点:
    加载不必要的类会浪费内存,尤其是在只需要访问类的元数据时。
  • 直接操作字节码(第二种方式)
    直接解析 .class 文件时,类并不需要被 JVM 加载到堆内存中。你可以仅通过读取 .class 文件内容获取元数据,而不需要将整个类实例化。这意味着你可以根据需要按需访问和处理类的元数据,而不必加载整个类。
  • 优点:你可以更加高效地控制哪些类被处理,减少不必要的内存占用和 GC 开销。
  1. 性能差异
  • 反射的运行时开销:由于反射在运行时需要动态查找类、方法和字段,且要进行权限检查等操作,因此相比于直接读取字节码的方式,反射的操作速度较慢,特别是在频繁调用反射 API 的场景下。反射本质上是通过 JVM 提供的 API 间接访问类的信息,会有一定的开销。
  • 直接操作字节码的效率:操作字节码文件则跳过了类加载和权限检查步骤,直接从字节码文件中提取类信息,性能更加高效。由于直接从磁盘或内存中读取 .class 文件,处理速度更快,而且可以避免 JVM 的动态查找和检查过程。
  1. 按需加载 vs 完整加载
  • 反射:反射机制一般会加载整个类,即使你只需要获取某些元数据(如方法名、字段名),但类的所有元数据都会被加载到内存中。
  • 直接操作字节码:你可以通过读取 .class 文件的字节码结构按需提取元数据,而无需加载整个类或实例化对象。你可以只读取所需的部分信息,例如类的常量池、方法描述符等,从而提升性能和内存利用效率。
扩:

Java 中的反射解析的是JVM 中已经加载到内存中的类对象Class 对象)。这些类对象是由 JVM 在加载 .class 文件时生成的。当 Java 程序运行时,JVM 会将 .class 文件加载到内存中,并创建一个与该类对应的 Class 对象。这个 Class 对象包含了该类的元数据(如类名、方法、字段、构造函数、注解等),并且通过 Java 的反射机制可以访问这些元数据。

接下来对ClassPathBeanDefinitionScanner的scan方法进行源码解析:

public int scan(String... basePackages) {
    // 获取当前注册表中的 Bean 定义数量,并存储在变量 beanCountAtScanStart 中,用于后续计算新增的 Bean 数量
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

    // 调用 doScan 方法,传入 basePackages 参数,开始扫描指定的包路径中的 Bean 定义
    this.doScan(basePackages);

    // 如果 includeAnnotationConfig 为 true,则注册注解配置的处理器(如 @Configuration、@Component 等)
    // 这将确保这些注解可以正常工作,通常用于 Spring 的注解驱动的配置
    if (this.includeAnnotationConfig) {
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    // 返回扫描后注册表中新增的 Bean 定义数量
    // 计算方式是当前 Bean 定义总数减去扫描开始前的数量
    return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}

核心方法是doScan函数:

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    // 检查传入的包路径参数 basePackages 是否为空,若为空则抛出异常
    Assert.notEmpty(basePackages, "At least one base package must be specified");

    // 创建一个空的 LinkedHashSet 集合用于存储扫描到的 BeanDefinitionHolder
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

    // 遍历传入的包路径(basePackages),获取要扫描的包路径
    String[] var3 = basePackages;
    int var4 = basePackages.length;

    for (int var5 = 0; var5 < var4; ++var5) {
        // 获取当前遍历到的包路径
        String basePackage = var3[var5];

        // 调用 findCandidateComponents 方法,查找该包路径下所有符合条件的 Bean 定义
        Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
        Iterator var8 = candidates.iterator();

        // 遍历所有符合条件的 BeanDefinition
        while (var8.hasNext()) {
            BeanDefinition candidate = (BeanDefinition) var8.next();

            // 解析每个 Bean 的作用域(scope),并设置到 BeanDefinition 中
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());

            // 生成 Bean 的名称(beanName)
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

            // 如果 BeanDefinition 是 AbstractBeanDefinition 类型,执行后置处理
            if (candidate instanceof AbstractBeanDefinition) {
                AbstractBeanDefinition abstractBeanDefinition = (AbstractBeanDefinition) candidate;
                this.postProcessBeanDefinition(abstractBeanDefinition, beanName);
            }

            // 如果 BeanDefinition 是 AnnotatedBeanDefinition 类型,处理常用注解(如 @Lazy、@Primary 等)
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) candidate;
                AnnotationConfigUtils.processCommonDefinitionAnnotations(annotatedBeanDefinition);
            }

            // 检查是否可以注册该 Bean(检查重复定义等情况)
            if (this.checkCandidate(beanName, candidate)) {
                // 将 BeanDefinition 封装到 BeanDefinitionHolder 中
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);

                // 应用作用域代理模式(如果需要),比如为 request、session 等作用域创建代理对象
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

                // 将 BeanDefinitionHolder 添加到集合中
                beanDefinitions.add(definitionHolder);

                // 注册该 BeanDefinition 到 BeanFactory(将其注册到 Spring 容器中)
                this.registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }

    // 返回扫描得到的 BeanDefinitionHolder 集合
    return beanDefinitions;
}

再看查找候选者candidate的相关代码:

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    // 判断是否存在组件索引(componentsIndex)且索引支持包含过滤器(include filters)
    // 如果存在组件索引并支持过滤器,则从索引中添加候选组件
    return this.componentsIndex != null && this.indexSupportsIncludeFilters() 
        // 如果有组件索引,并且支持过滤器,则通过索引来获取候选组件
        ? this.addCandidateComponentsFromIndex(this.componentsIndex, basePackage) 
        // 否则通过扫描的方式获取候选组件
        : this.scanCandidateComponents(basePackage);
}
扩:

Spring 5 的新特性,直接从 META-INF/spring.components 组件索引文件中加载符合条件的 Bean,避免了包扫描,用于提升启动速度。

Spring 5 升级的其中一个重点就是提升了注解驱动的启动性能。META-INF/spring.components 这个文件类似于一个 “组件索引” 文件。

我们将需要加载的组件 (Bean 定义) 预先以键值对的形式配置到该文件中。当项目中存在 META-INF/spring.components 文件并且文件中配置了属性时,Spring 不会进行包扫描,而是直接读取 META-INF/spring.components 中组件的定义并直接加载,从而达到提升性能的目的。

如META-INF/spring.components记录了:


com.ydLcLass.Dog=org.springframework.stereotype.Component
com.ydLcLass.MyConfiguration=org.springframework.stereotype.Component

则会将Dog、MyConfiguration注册为@Component

进一步查看候选者的扫描:

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    // 创建一个 LinkedHashSet 用于存储扫描到的候选 BeanDefinition 对象
    LinkedHashSet candidates = new LinkedHashSet();

    try {
        // 将包名转换为资源路径
        String var10000 = this.resolveBasePackage(basePackage);
        // 构建扫描路径,形如 "classpath*:com/example/**/*.class"
        String packageSearchPath = "classpath*:" + var10000 + "/" + this.resourcePattern;
        // 获取匹配路径的所有资源(类文件、配置文件等)
        //Spring会将每一个定义的字节码文件加载成为一个Resource资源(包括内部类都是一个Resource资源)
		//此处是以资源(流)的方式加载(普通文件),而不是将一个类使用类加载器加载到jvm中。
        Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
        
        // 检查日志级别是否为 trace 或 debug
        boolean traceEnabled = this.logger.isTraceEnabled();
        boolean debugEnabled = this.logger.isDebugEnabled();

        Resource[] var7 = resources;
        int var8 = resources.length;

        // 遍历扫描到的资源
        for (int var9 = 0; var9 < var8; ++var9) {
            Resource resource = var7[var9];
            String filename = resource.getFilename();

            // 跳过包含 "$$" 的类(通常是由代理生成的类,如CGLIB生产的代理类文件)
            if (filename == null || !filename.contains("$$")) {
                // 如果启用了 trace 日志,则记录正在扫描的资源
                if (traceEnabled) {
                    this.logger.trace("Scanning " + resource);
                }

                try {
                    // 通过 MetadataReader 读取资源的元数据
                    MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);

                    // 检查该资源是否是候选组件,即是否符合TypeFilter类型过滤器的要求
                    //使用IncludeFilter。 就算目标类上没有@Component注解,它也会被扫描成为一-个Bean
					//使用ExcludeFilter, 就算目标类上面有QComponent注解也不会成为Bean
                    if (this.isCandidateComponent(metadataReader)) {
                        // 如果是候选组件,创建 BeanDefinition
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setSource(resource);

                        // 进一步验证该组件是否是合格的候选组件
                        if (this.isCandidateComponent((AnnotatedBeanDefinition) sbd)) {
                            // 如果启用了 debug 日志,记录该候选组件
                            if (debugEnabled) {
                                this.logger.debug("Identified candidate component class: " + resource);
                            }

                            // 将合格的组件添加到 candidates 集合中
                            candidates.add(sbd);
                        } else if (debugEnabled) {
                            // 如果该类不是具体的顶级类,记录 debug 日志
                            this.logger.debug("Ignored because not a concrete top-level class: " + resource);
                        }
                    } else if (traceEnabled) {
                        // 如果不符合筛选条件,记录 trace 日志
                        this.logger.trace("Ignored because not matching any filter: " + resource);
                    }
                } catch (FileNotFoundException var14) {
                    // 如果资源文件找不到,记录 trace 日志并跳过该资源
                    if (traceEnabled) {
                        this.logger.trace("Ignored non-readable " + resource + ": " + var14.getMessage());
                    }
                } catch (ClassFormatException var15) {
                    // 如果类格式异常,根据配置决定是否忽略该异常
                    if (!shouldIgnoreClassFormatException) {
                        throw new BeanDefinitionStoreException("Incompatible class format in " + resource + ": set system property 'spring.classformat.ignore' to 'true' if you mean to ignore such files during classpath scanning", var15);
                    }

                    if (debugEnabled) {
                        // 记录 debug 日志,表示类格式不兼容被忽略
                        this.logger.debug("Ignored incompatible class format in " + resource + ": " + var15.getMessage());
                    }
                } catch (Throwable var16) {
                    // 捕获任何其他异常并抛出 BeanDefinitionStoreException 异常
                    throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var16);
                }
            }
        }

        // 返回扫描到的候选组件
        return candidates;
    } catch (IOException var17) {
        // 捕获 I/O 异常并抛出 BeanDefinitionStoreException 异常
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var17);
    }
}

第二章 基础工具

一、内省api

内省(Introspection)是 Java 语言中用于 Bean 类属性和事件处理的机制,通过它可以动态地获取类的信息,尤其是 Bean 类的属性和事件。内省允许程序在运行时检查对象及其类的特性,而不需要提前知道对象的具体类型。

内省机制是一种 Java 提供的动态分析类信息的手段,Spring 使用该机制自动处理 Bean 的依赖注入、事件监听等功能,大大提高了开发的灵活性和自动化程度。

扩:反射 V S VS VS内省

  • 内省:专注于 Java Bean 类的属性和事件的获取与设置,使用相对简单,主要处理符合 Bean 规范的类。
  • 反射:更为通用和强大的机制,允许操作类的所有成员,但使用复杂度和性能开销较大。

JavaBean 与普通类的区别
虽然 JavaBean 只是一个类,但它与普通类有几点不同:

  • JavaBean 必须遵循特定的命名约定(如 gettersetter 方法)。
  • JavaBean 必须有一个无参的构造函数。
  • JavaBean 必须实现 Serializable 接口。
  • JavaBean 主要用于封装数据,通常不包含复杂的业务逻辑。

在这里插入图片描述

内省机制是通过 Introspector 类获取 BeanInfo,然后通过 BeanInfo 获取属性描述器 PropertyDescriptor,最终利用这些描述器来获取属性的 getter 和 setter 方法,从而通过反射调用这些方法进行属性的操作。

public void testIntrospect() throws Exception {
    // 获取 User 类的 BeanInfo 对象,不包含从 Object 类继承的属性
    BeanInfo info = Introspector.getBeanInfo(User.class, Object.class);

    // 获取该类的所有属性描述器
    PropertyDescriptor[] pds = info.getPropertyDescriptors();

    // 遍历每个属性描述器
    for (PropertyDescriptor pd : pds) {
        // 获取属性的名称并记录到日志
        logger.info("pd.getName() --> {}", pd.getName());

        // 获取属性的 getter 方法并记录到日志
        logger.info("pd.getReadMethod() --> {}", pd.getReadMethod());

        // 获取属性的 setter 方法并记录到日志
        logger.info("pd.getWriteMethod() --> {}", pd.getWriteMethod());

        // 获取属性的类型并记录到日志
        logger.info("pd.getPropertyType() --> {}", pd.getPropertyType());

        // 获取属性的简短描述并记录到日志
        logger.info("pd.getShortDescription() --> {}", pd.getShortDescription());
    }
}

当涉及到设置值,就使用到了反射的函数:

public void testIntrospect() throws Exception {
    // 创建一个 User 对象
    User user = new User();

    // 创建一个 PropertyDescriptor,用于描述 User 类的 "age" 属性
    PropertyDescriptor descriptor = new PropertyDescriptor("age", User.class);

    // 获取该属性的 setter 方法
    Method writeMethod = descriptor.getWriteMethod();

    // 使用反射调用 setter 方法,将 age 属性的值设置为 13
    writeMethod.invoke(user, 13);

    // 记录当前 user 对象的状态,输出 user 对象的信息
    Logger.info("user --> {}", user);

    // 获取该属性的 getter 方法
    Method readMethod = descriptor.getReadMethod();

    // 使用反射调用 getter 方法,获取 age 属性的值,并记录到日志
    Logger.info("age --> {}", readMethod.invoke(user));
}

在 Spring 中,BeanUtils 是一个非常有用的工具类,主要用于简化 JavaBean 的操作。

  • 导包
<dependency>
	<groupId>commons-beanutils</ groupId>
	<artifactId>commons-beanutils</ artifactId>
	<version>1.9.4</version>
</ dependency>

二、更强的反射工具

BeanWrapper 是 Spring 框架中用于操作 JavaBean 属性的一个核心工具类。它封装了 Java 的反射机制,简化了对 JavaBean 属性的读取、设置、类型转换等操作。在 Spring 框架内部,BeanWrapper 通常与 BeanFactoryBeanDefinition 配合使用,用于管理和实例化 Bean。

例子:获取bean元数据并完成初始化

public void testBeanWrapper() throws ClassNotFoundException {
    // 通过包扫描获取的 Bean 元数据
    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
    
    // 设置 Bean 类的名称(全限定类名)
    beanDefinition.setBeanClassName("com.ydlclass.User");

    // 创建一个用于保存属性值的对象
    MutablePropertyValues values = new MutablePropertyValues();

    // 添加属性 "username",值为 "tom"
    values.addPropertyValue("username", "tom");

    // 添加属性 "age",值为 12
    values.addPropertyValue("age", 12);

    // 将属性值设置到 BeanDefinition 中
    beanDefinition.setPropertyValues(values);

    // 获取类的 Class 对象,通过类名加载类
    Class<?> clazz = Class.forName(beanDefinition.getBeanClassName());

    // 创建一个 BeanWrapper 对象,使用 clazz 进行实例化
    BeanWrapper beanWrapper = new BeanWrapperImpl(clazz);

    // 设置属性值,将 BeanDefinition 中的属性值注入到 Bean 实例中
    beanWrapper.setPropertyValues(beanDefinition.getPropertyValues());

    // 获取实例化后的 Bean 对象
    Object instance = beanWrapper.getWrappedInstance();

    // 输出实例对象的内容到日志
    Logger.info("obj --> {}", instance);//obj --> User-username= 'tom' age=12} 
}

批量构造

// 1. 通过任意形式捕获 beanDefinition
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(registry);

// 从指定的 XML 配置文件加载 Bean 定义
xmlReader.loadBeanDefinitions("classpath:bean.xml");

// 2. 通过反射实例化
String[] definitionNames = registry.getBeanDefinitionNames();

// 遍历所有的 Bean 定义名称
for (String definitionName : definitionNames) {
    // 获取 BeanDefinition 对象
    BeanDefinition beanDefinition = registry.getBeanDefinition(definitionName);

    // 获取 Bean 的类名
    String beanClassName = beanDefinition.getBeanClassName();

    // 通过类名加载该类,返回 Class 对象
    Class<?> aClass = Class.forName(beanClassName);

    // 3. 使用 BeanWrapper 包裹实例,使其更方便使用反射方法
    BeanWrapper beanWrapper = new BeanWrapperImpl(aClass);

    // 设置属性值,将 BeanDefinition 中的属性值注入到 Bean 实例中
    beanWrapper.setPropertyValues(beanDefinition.getPropertyValues());

    // 获取实例化后的 Bean 对象
    Object bean = beanWrapper.getWrappedInstance();

    // 输出 Bean 对象的信息(取决于该类的 toString 方法)
    System.out.println(bean);
}

目前还存在一个格式转换的问题

三、ResolvableType

ResolvableType 是一个非常强大的工具类,它简化了 Java 反射 API 的使用,尤其是在处理复杂的泛型类型时,它能方便地解析字段、方法参数、返回类型及超类、接口的泛型参数。在 Spring 框架中,ResolvableType 被广泛用于处理泛型依赖注入、事件机制以及其他需要动态解析类型的场景。

例子:

import org.springframework.core.ResolvableType;
import java.util.List;

public class ResolvableTypeExample {

    // 定义一个具有泛型的字段
    private List<String> strings;

    public static void main(String[] args) throws NoSuchFieldException {
        // 获取字段的 ResolvableType
        ResolvableType type = ResolvableType.forField(ResolvableTypeExample.class.getDeclaredField("strings"));

        // 获取该字段的原始类型,即 List
        System.out.println("Raw class: " + type.getRawClass());

        // 获取该字段的泛型参数类型,即 String
        System.out.println("Generic type: " + type.getGeneric(0).resolve());
    }
}

输出:

Raw class: interface java.util.List
Generic type: class java.lang.String

四、类型转化

我们从xml中搜集到的所有数据都是【字符串】,但是实际的类中的成员变量可能是数字,数组,集合,或者是复杂的引用数据类型,所以spring给我们提供了强大的转换服务(conversionService接口) .

1、转换服务

ConversionService接口可以根据源类型和目标类型进行判断是否可以转换,并执行转换:

public interface ConversionService {
    /**
     * 判断是否可以将源类型转换为目标类型。
     * @param sourceType 源类型,可以为空。
     * @param targetType 目标类型,不能为空。
     * @return 如果可以转换,返回true,否则返回false。
     */
    boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);

    /**
     * 判断是否可以将源类型描述符表示的类型转换为目标类型描述符表示的类型。
     * @param sourceType 源类型描述符,可以为空。
     * @param targetType 目标类型描述符,不能为空。
     * @return 如果可以转换,返回true,否则返回false。
     */
    boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);

    /**
     * 将给定的源对象转换为目标类型。
     * @param <T> 目标类型的类型参数。
     * @param source 源对象,可以为空。
     * @param targetType 目标类型,不能为空。
     * @return 转换后的对象,如果转换失败或源对象为空,返回null。
     */
    @Nullable
    <T> T convert(@Nullable Object source, Class<T> targetType);

    /**
     * 将给定的源对象从源类型描述符表示的类型转换为目标类型描述符表示的类型。
     * @param source 源对象,可以为空。
     * @param sourceType 源类型描述符,可以为空。
     * @param targetType 目标类型描述符,不能为空。
     * @return 转换后的对象,如果转换失败或源对象为空,返回null。
     */
    Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
}

接下来看一个具体的实现类:

/**
 * DefaultConversionService 是一个继承自 GenericConversionService 的默认转换服务,
 * 提供了丰富的默认转换器,并且支持线程安全的单例模式。
 */
public class DefaultConversionService extends GenericConversionService {

    // 共享的 DefaultConversionService 实例,用于单例模式
    @Nullable
    private static volatile DefaultConversionService sharedInstance;

    // 构造函数,实例化时自动添加默认的转换器
    public DefaultConversionService() {
        addDefaultConverters(this); // 向当前实例添加默认转换器
    }

    /**
     * 获取共享的单例 DefaultConversionService 实例。
     * 如果实例不存在,会初始化一个新实例。
     */
    public static ConversionService getSharedInstance() {
        // 获取已有的 sharedInstance,如果已存在则返回
        DefaultConversionService cs = sharedInstance;
        if (cs == null) {
            // 使用同步块以确保线程安全
            Class var1 = DefaultConversionService.class;
            synchronized (DefaultConversionService.class) {
                cs = sharedInstance;
                if (cs == null) {
                    cs = new DefaultConversionService(); // 初始化新实例
                    sharedInstance = cs; // 更新共享实例
                }
            }
        }

        return cs; // 返回共享实例
    }

    /**
     * 向 ConverterRegistry 中添加默认的转换器。
     * 包括基本数据类型、集合类型、时区、以及一些特定的对象。
     */
    public static void addDefaultConverters(ConverterRegistry converterRegistry) {
        addScalarConverters(converterRegistry); // 添加标量类型的转换器
        addCollectionConverters(converterRegistry); // 添加集合类型的转换器
        // 添加更多特定类型的转换器
        converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
        converterRegistry.addConverter(new StringToTimeZoneConverter());
        converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
        converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());
        converterRegistry.addConverter(new ObjectToObjectConverter());
        converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
        converterRegistry.addConverter(new FallbackObjectToStringConverter());
        converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
    }

    /**
     * 添加集合类型的转换器,处理数组、集合、Map 等类型之间的转换。
     */
    public static void addCollectionConverters(ConverterRegistry converterRegistry) {
        ConversionService conversionService = (ConversionService) converterRegistry;
        // 添加数组与集合之间的相互转换
        converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
        converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));
        converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
        converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
        converterRegistry.addConverter(new MapToMapConverter(conversionService));
        // 添加数组与字符串之间的转换
        converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
        converterRegistry.addConverter(new StringToArrayConverter(conversionService));
        // 添加对象与数组/集合之间的转换
        converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
        converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));
        converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
        converterRegistry.addConverter(new StringToCollectionConverter(conversionService));
        converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
        converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
        // 添加 Stream 类型的转换器
        converterRegistry.addConverter(new StreamConverter(conversionService));
    }

    /**
     * 添加标量类型的转换器,处理数字、字符、布尔等基本数据类型的转换。
     */
    private static void addScalarConverters(ConverterRegistry converterRegistry) {
        // 添加 Number 类型的转换工厂,支持数字类型间的转换
        converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
        // 添加 String 到 Number 的转换工厂
        converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
        // 添加数字到字符串的转换
        converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());
        // 添加 String 到 Character 的转换
        converterRegistry.addConverter(new StringToCharacterConverter());
        // 添加 Character 到 String 的转换
        converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());
        // 添加 Number 到 Character 的转换
        converterRegistry.addConverter(new NumberToCharacterConverter());
        // 添加 Character 到 Number 的转换工厂
        converterRegistry.addConverterFactory(new CharacterToNumberFactory());
        // 添加 String 到 Boolean 的转换
        converterRegistry.addConverter(new StringToBooleanConverter());
        // 添加 Boolean 到 String 的转换
        converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
        // 添加 String 到 Enum 的转换工厂
        converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
        // 添加 Enum 到 String 的转换
        converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));
        // 添加 Integer 到 Enum 的转换工厂
        converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
        // 添加 Enum 到 Integer 的转换
        converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));
        // 添加 String 到 Locale 的转换
        converterRegistry.addConverter(new StringToLocaleConverter());
        // 添加 Locale 到 String 的转换
        converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());
        // 添加 String 到 Charset 的转换
        converterRegistry.addConverter(new StringToCharsetConverter());
        // 添加 Charset 到 String 的转换
        converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());
        // 添加 String 到 Currency 的转换
        converterRegistry.addConverter(new StringToCurrencyConverter());
        // 添加 Currency 到 String 的转换
        converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());
        // 添加 String 到 Properties 的转换
        converterRegistry.addConverter(new StringToPropertiesConverter());
        // 添加 Properties 到 String 的转换
        converterRegistry.addConverter(new PropertiesToStringConverter());
        // 添加 String 到 UUID 的转换
        converterRegistry.addConverter(new StringToUUIDConverter());
        // 添加 UUID 到 String 的转换
        converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
        // 添加 String 到 Pattern 的转换
        converterRegistry.addConverter(new StringToPatternConverter());
        // 添加 Pattern 到 String 的转换
        converterRegistry.addConverter(Pattern.class, String.class, new ObjectToStringConverter());

        // 如果检测到 Kotlin 环境,添加 String 和 Regex 之间的转换
        if (KotlinDetector.isKotlinPresent()) {
            converterRegistry.addConverter(new StringToRegexConverter());
            converterRegistry.addConverter(Regex.class, String.class, new ObjectToStringConverter());
        }
    }
}

上述的代码,类似bean的管理:注册器管理着众多的转换器,为我们提供了一个转化服务。

其中addConverter方法接收的是一个GenericConverter converter类型的转换器;这个接口源码:

/**
 * 通用转换器接口,定义如何在源类型和目标类型之间进行转换
 */
public interface GenericConverter {
    
    /**
     * 返回当前转换器支持的源类型和目标类型对的集合
     * @return 可转换的类型对集合,类型对通过 ConvertiblePair 表示
     */
    @Nullable
    Set<GenericConverter.ConvertiblePair> getConvertibleTypes();

    /**
     * 执行从源对象到目标类型的实际转换
     * @param source 源对象,可能为 null
     * @param sourceType 源对象的类型描述符
     * @param targetType 目标类型的描述符
     * @return 转换后的对象,可能为 null
     */
    @Nullable
    Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);

    /**
     * 内部类,用于封装一个源类型和目标类型的配对
     */
    public static final class ConvertiblePair {
        private final Class<?> sourceType; // 源类型
        private final Class<?> targetType; // 目标类型

        /**
         * 构造函数,创建一个源类型和目标类型的配对
         * @param sourceType 源类型,不能为空
         * @param targetType 目标类型,不能为空
         */
        public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
            // 验证参数不为空
            Assert.notNull(sourceType, "Source type must not be null");
            Assert.notNull(targetType, "Target type must not be null");
            this.sourceType = sourceType;
            this.targetType = targetType;
        }

        /**
         * 获取源类型
         * @return 源类型的 Class 对象
         */
        public Class<?> getSourceType() {
            return this.sourceType;
        }

        /**
         * 获取目标类型
         * @return 目标类型的 Class 对象
         */
        public Class<?> getTargetType() {
            return this.targetType;
        }
    }
}

进一步我们查看GenericConverter其中一个实现类StringToArrayConverter的源码实现:

/**
 * StringToArrayConverter 是一个用于将字符串转换为数组的转换器实现,
 * 实现了 ConditionalGenericConverter 接口。它基于逗号分隔的字符串将其转换为目标数组类型。
 */
final class StringToArrayConverter implements ConditionalGenericConverter {

    // ConversionService 用于处理具体的转换过程
    private final ConversionService conversionService;

    /**
     * 构造函数,接收一个 ConversionService 对象
     * @param conversionService 用于元素类型的进一步转换
     */
    public StringToArrayConverter(ConversionService conversionService) {
        this.conversionService = conversionService;
    }

    /**
     * 返回该转换器支持的源类型和目标类型对
     * @return 只支持 String 到 Object[] 的转换
     */
    public Set<ConvertiblePair> getConvertibleTypes() {
        return Collections.singleton(new ConvertiblePair(String.class, Object[].class));
    }

    /**
     * 判断是否能够匹配源类型和目标类型
     * @param sourceType 源类型的描述符
     * @param targetType 目标类型的描述符
     * @return 如果元素可以转换,则返回 true
     */
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        // 检查元素是否可以转换
        return ConversionUtils.canConvertElements(sourceType, targetType.getElementTypeDescriptor(), this.conversionService);
    }

    /**
     * 将字符串源对象转换为目标数组类型
     * @param source 源对象,可能为 null
     * @param sourceType 源类型的描述符
     * @param targetType 目标类型的描述符
     * @return 转换后的目标数组对象,或者 null
     */
    @Nullable
    public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        if (source == null) {
            // 如果源对象为 null,则返回 null
            return null;
        } else {
            // 将源对象强制转换为字符串
            String string = (String)source;
            // 使用逗号分隔字符串生成数组
            String[] fields = StringUtils.commaDelimitedListToStringArray(string);
            // 获取目标数组的元素类型描述符
            TypeDescriptor targetElementType = targetType.getElementTypeDescriptor();
            // 确保目标元素类型不为 null
            Assert.state(targetElementType != null, "No target element type");
            // 根据目标元素类型创建目标数组对象
            Object target = Array.newInstance(targetElementType.getType(), fields.length);

            // 遍历字符串字段数组,将每个字段转换为目标类型的元素
            for(int i = 0; i < fields.length; ++i) {
                String sourceElement = fields[i];
                // 去除字段的空格,并进行类型转换
                Object targetElement = this.conversionService.convert(sourceElement.trim(), sourceType, targetElementType);
                // 将转换后的元素放入目标数组中
                Array.set(target, i, targetElement);
            }

            // 返回最终的目标数组对象
            return target;
        }
    }
}

接下来尝试写一个自己的converter

/**
 * TypeStringValueToIntegerConverter 类实现了 GenericConverter 接口,
 * 用于将 TypedStringValue 类型的对象转换为 Integer 类型的对象。
 */
public class TypeStringValueToIntegerConverter implements GenericConverter {

    /**
     * 返回此转换器支持的源类型和目标类型对。
     * 在这里,转换器支持将 TypedStringValue 类型转换为 Integer 类型。
     * 
     * @return 该转换器支持的 ConvertiblePair 集合
     */
    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        // 返回一个包含源类型为 TypedStringValue,目标类型为 Integer 的 ConvertiblePair
        return Collections.singleton(new ConvertiblePair(TypedStringValue.class, Integer.class));
    }

    /**
     * 将给定的源对象从 TypedStringValue 转换为 Integer。
     * 
     * @param source 源对象,期望是 TypedStringValue 类型
     * @param sourceType 源对象的类型描述符
     * @param targetType 目标类型的描述符
     * @return 转换后的 Integer 对象
     */
    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        // 将源对象强制转换为 TypedStringValue 类型
        TypedStringValue typedStringValue = (TypedStringValue) source;
        // 使用 Integer 的 valueOf 方法将字符串值转换为 Integer
        return Integer.valueOf(typedStringValue.getValue());
    }
}

我们需要在批量构造的代码中,加上转化服务:

// 1. 通过任意形式捕获 beanDefinition
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(registry);

// 从指定的 XML 配置文件加载 Bean 定义
xmlReader.loadBeanDefinitions("classpath:bean.xml");

// 2. 通过反射实例化
String[] definitionNames = registry.getBeanDefinitionNames();

// 遍历所有的 Bean 定义名称
for (String definitionName : definitionNames) {
    // 获取 BeanDefinition 对象
    BeanDefinition beanDefinition = registry.getBeanDefinition(definitionName);

    // 获取 Bean 的类名
    String beanClassName = beanDefinition.getBeanClassName();

    // 通过类名加载该类,返回 Class 对象
    Class<?> aClass = Class.forName(beanClassName);

    // 3. 使用 BeanWrapper 包裹实例,使其更方便使用反射方法
    BeanWrapper beanWrapper = new BeanWrapperImpl(aClass);

	// 4.需要自定义转化服务
	DefaultConversionService service = new DefaultConversionService();
	service.addConverter(new TypeStringValueToIntegerConverter());

	beanWrapper.setConversionService(service);

    // 设置属性值,将 BeanDefinition 中的属性值注入到 Bean 实例中
    beanWrapper.setPropertyValues(beanDefinition.getPropertyValues());

    // 获取实例化后的 Bean 对象
    Object bean = beanWrapper.getWrappedInstance();

    // 输出 Bean 对象的信息(取决于该类的 toString 方法)
    System.out.println(bean);
}

2、converter结构

接下来我们查看这个注册器的源码,通过converterRegistry.addConverter追踪:

public void addConverter(GenericConverter converter) {  
    this.converters.add(converter);  
    this.invalidateCache();  
}

这个this.converters在代码中对应着一个对象:

private final GenericConversionService.Converters converters = new GenericConversionService.Converters();

查看Converters类:

/**
 * Converters 是一个内部静态类,主要用于管理和操作转换器(GenericConverter)的集合。
 * 它负责注册、移除、查找和匹配适当的转换器来处理不同类型之间的转换。
 */
private static class Converters {
    // 全局转换器的集合,线程安全的集合类 CopyOnWriteArraySet 用于存储。
    private final Set<GenericConverter> globalConverters = new CopyOnWriteArraySet<>();
    // 用于存储具体的 ConvertiblePair 到 ConvertersForPair 的映射,初始容量为 256。
    private final Map<ConvertiblePair, GenericConversionService.ConvertersForPair> converters = new ConcurrentHashMap<>(256);

    // 私有构造函数,避免外部实例化
    private Converters() {
    }

    /**
     * 添加转换器到 converters 集合中。如果 ConvertibleTypes 为空,
     * 该转换器将被添加到全局转换器集中,否则添加到具体的可匹配的类型对。
     *
     * @param converter 要添加的转换器
     */
    public void add(GenericConverter converter) {
        Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
        // 如果 convertibleTypes 为 null,断言该转换器必须是 ConditionalConverter
        if (convertibleTypes == null) {
            Assert.state(converter instanceof ConditionalConverter, "Only conditional converters may return null convertible types");
            this.globalConverters.add(converter);  // 添加到全局转换器集合
        } else {
            // 遍历 ConvertiblePair 并添加到对应的匹配集合
            for (ConvertiblePair convertiblePair : convertibleTypes) {
                this.getMatchableConverters(convertiblePair).add(converter);
            }
        }
    }

    /**
     * 根据源类型和目标类型移除某个转换器。
     *
     * @param sourceType 源类型
     * @param targetType 目标类型
     */
    public void remove(Class<?> sourceType, Class<?> targetType) {
        this.converters.remove(new ConvertiblePair(sourceType, targetType));
    }

    /**
     * 查找与给定的源类型和目标类型相匹配的转换器。
     * 会从类的继承层次结构中依次查找匹配的转换器。
     *
     * @param sourceType 源类型描述符
     * @param targetType 目标类型描述符
     * @return 匹配的转换器,如果没有找到则返回 null
     */
    @Nullable
    public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
        // 获取源类型和目标类型的类层次结构
        List<Class<?>> sourceCandidates = this.getClassHierarchy(sourceType.getType());
        List<Class<?>> targetCandidates = this.getClassHierarchy(targetType.getType());

        // 遍历源类型和目标类型候选项进行匹配
        for (Class<?> sourceCandidate : sourceCandidates) {
            for (Class<?> targetCandidate : targetCandidates) {
                ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);
                GenericConverter converter = this.getRegisteredConverter(sourceType, targetType, convertiblePair);
                if (converter != null) {
                    return converter;  // 找到匹配的转换器
                }
            }
        }
        return null;  // 未找到匹配的转换器
    }
}

其中converters的结构如下图所示:
在这里插入图片描述

五、resource匹配

1、内置的Resource的实现

Spring框架包含了几种常用的Resource实现类,用于访问不同类型的资源。以下是这些实现类的介绍:

  1. UrlResource:
    • 用于封装 java.net.URL 对象,能够通过 URL 访问任何类型的资源,如文件、HTTPS目标、FTP目标等。
    • 支持的 URL 前缀包括:
      • file: 访问本地文件系统路径
      • https: 通过 HTTPS 协议访问资源
      • ftp: 通过 FTP 协议访问资源
  2. ClassPathResource:
    • 用于从类路径(classpath)中获取资源。
    • 使用线程上下文类加载器、给定的类加载器或类自身来加载资源,通常用于读取项目中的配置文件或类路径下的资源。
  3. FileSystemResource:
    • 基于 java.io.File 的实现,用于操作系统文件系统中的文件资源。
    • 可以直接访问本地文件系统上的文件。
  4. InputStreamResource:
    • 基于给定的 InputStream 对象的资源实现。
    • 适用于没有具体资源实现时的情况,如从网络连接或其他来源获取的流对象。
  5. ByteArrayResource:
    • 使用给定的字节数组作为数据源的资源实现。
    • 通常用于需要通过内存中的字节数组来处理数据的场景。

这些内置的 Resource 实现为 Spring 提供了灵活的资源访问方式,能够处理不同来源的文件和数据资源。

下面是三个测试用例的实现示例,使用了 Spring 框架的 Resource 实现类和 commons-io 工具包来进行资源的读写操作。

测试用例 1:测试 UrlResource

import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;

import java.io.FileOutputStream;
import java.io.IOException;

public class ResourceTest {

    @Test
    public void testUrlResource() throws IOException {
        // 创建一个UrlResource对象,用于下载资源
        Resource resource = new UrlResource("https://d1dir1.qq.com/qqfile/qq/PCQQ9.7.0/QQ9.7.0.28921.exe");

        // 使用 FileOutputStream 将下载的文件保存到本地路径 D://
        FileOutputStream fos = new FileOutputStream("D://"+resource.getFilename());

        // 使用 commons-io 工具包将资源输入流复制到本地输出流
        IOUtils.copy(resource.getInputStream(), fos);

        // 关闭流
        fos.close();
    }
}

测试用例 2:测试 FileSystemResource

import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import java.io.IOException;

public class ResourceTest {

    @Test
    public void testFileSystemResource() throws IOException {
        // 创建 FileSystemResource 对象,指向文件系统中的某个文件
        Resource resource = new FileSystemResource("D:/spring/spring.xml");

        // 创建缓冲区读取数据
        byte[] buffer = new byte[1024 * 100];
        int offset = IOUtils.read(resource.getInputStream(), buffer);

        // 打印读取到的数据
        System.out.println(new String(buffer, 0, offset));
    }
}

测试用例 3:测试 ClassPathResource

import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;

public class ResourceTest {

    @Test
    public void testClassPathResource() throws IOException {
        // 创建 ClassPathResource 对象,从类路径中加载资源
        Resource resource = new ClassPathResource("spring.xml");

        // 创建缓冲区读取数据
        byte[] buffer = new byte[1024 * 100];
        int offset = IOUtils.read(resource.getInputStream(), buffer);

        // 打印读取到的数据
        System.out.println(new String(buffer, 0, offset));
    }
}

PathMatchingResourcePatternResolver 是 Spring 框架中用于加载资源的实用类,支持通过路径模式匹配加载资源。

  • getResource(location) 用于获取单个资源。
  • getResources(locationPattern) 可以使用通配符匹配来获取多个资源。
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

public class ResourceLoaderExample {
    public static void main(String[] args) throws Exception {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        // 加载单个网络资源
        Resource resource = resolver.getResource("https://dldir1.qq.com/qqfile/qq/PCQQ9.7.1/QQ9.7.1.exe");
        System.out.println("Resource URI: " + resource.getURI());

        // 加载类路径中的 XML 文件
        Resource xmlResource = resolver.getResource("classpath:bean.xml");
        System.out.println("XML Resource URI: " + xmlResource.getURI());

        // 加载匹配 classpath 的多个资源
        Resource[] resources = resolver.getResources("classpath*:META-INF/spring.factories");
        for (Resource res : resources) {
            System.out.println("Resource URI: " + res.getURI());
        }
    }
}

2、加载xml

回到之前的代码:

// 创建一个 BeanDefinitionRegistry 实例,用于保存和管理 Bean 定义
BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();

// 创建一个 XmlBeanDefinitionReader 实例,并将其与 BeanDefinitionRegistry 关联
// XmlBeanDefinitionReader 负责从 XML 文件中读取 Bean 的定义,并将其注册到指定的 BeanDefinitionRegistry 中
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(registry);

// 从指定的 XML 配置文件中加载 Bean 定义
// 这里指定的文件路径为 "classpath:bean.xml",表示文件位于类路径中
// XmlBeanDefinitionReader 会解析该文件中的所有 Bean 定义并将它们注册到 registry 中
xmlReader.loadBeanDefinitions("classpath:bean.xml");

查看loadBeanDefinitions源码:

// 加载指定位置的 Bean 定义
// location: Bean 配置文件的路径
// actualResources: 用来存储加载成功的资源 (Resource) 对象,可能为 null
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {

    // 获取资源加载器
    ResourceLoader resourceLoader = this.getResourceLoader();
    
    // 如果没有可用的 ResourceLoader,则抛出异常
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException("Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    } else {
        int count;

        // 如果 ResourceLoader 是 ResourcePatternResolver 的实例(支持路径模式匹配),则使用它来加载资源
        if (resourceLoader instanceof ResourcePatternResolver) {
            ResourcePatternResolver resourcePatternResolver = (ResourcePatternResolver) resourceLoader;

            try {
                // 使用资源模式解析器获取符合 location 路径模式的所有资源
                Resource[] resources = resourcePatternResolver.getResources(location);

                // 调用 loadBeanDefinitions(Resource[]) 方法加载这些资源中的 Bean 定义
                count = this.loadBeanDefinitions(resources);

                // 如果 actualResources 不为 null,则将所有成功加载的资源添加到 actualResources 集合中
                if (actualResources != null) {
                    Collections.addAll(actualResources, resources);
                }

                // 如果日志级别为 TRACE,则记录加载的 Bean 定义数量和位置
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
                }

                return count;
            } catch (IOException var7) {
                // 捕获 IO 异常并抛出 BeanDefinitionStoreException,表示资源模式解析时发生错误
                throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var7);
            }
        } else {
            // 如果 ResourceLoader 不是 ResourcePatternResolver 实例,则直接通过它加载单个资源
            Resource resource = resourceLoader.getResource(location);

            // 调用 loadBeanDefinitions(Resource) 方法加载该资源中的 Bean 定义
            count = this.loadBeanDefinitions((Resource) resource);

            // 如果 actualResources 不为 null,则将加载的资源添加到 actualResources 集合中
            if (actualResources != null) {
                actualResources.add(resource);
            }

            // 如果日志级别为 TRACE,则记录加载的 Bean 定义数量和位置
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
            }

            return count;
        }
    }
}

其中比较关键的两行:

Resource[] resources = resourcePatternResolver.getResources(location);

// 调用 loadBeanDefinitions(Resource[]) 方法加载这些资源中的 Bean 定义
count = this.loadBeanDefinitions(resources);

getResources即使用上小节的通配匹配获取资源;接下来查看核心函数loadBeanDefinitions

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {  
    Assert.notNull(resources, "Resource array must not be null");  
    int count = 0;  
    Resource[] var3 = resources;  
    int var4 = resources.length;  
  
    for(int var5 = 0; var5 < var4; ++var5) {  
        Resource resource = var3[var5];  
        count += this.loadBeanDefinitions((Resource)resource);  
    }  
  
    return count;  
}

继续深入:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    // 检查传入的 EncodedResource 是否为空,如果为空则抛出异常
    Assert.notNull(encodedResource, "EncodedResource must not be null");

    // 如果日志级别为 TRACE,记录日志,表示正在从 encodedResource 加载 XML Bean 定义
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Loading XML bean definitions from " + encodedResource);
    }

    // 获取当前正在加载的资源集合,确保不会出现循环加载
    Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();

    // 如果当前资源已经在加载集合中,则抛出异常,防止循环引用(即 XML 配置文件相互导入导致的无限递归)
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    } else {
        int var5;
        try {
            // 获取资源的输入流
            InputStream inputStream = encodedResource.getResource().getInputStream();

            try {
                // 创建 InputSource 对象,用于解析 XML 文件
                InputSource inputSource = new InputSource(inputStream);

                // 如果有指定的编码格式,则设置到 InputSource 中
                if (encodedResource.getEncoding() != null) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }

                // 调用核心方法 doLoadBeanDefinitions,解析 XML 并加载 Bean 定义
                var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            } catch (Throwable var12) {
                // 在解析 XML 过程中出现异常时,关闭输入流并抛出异常
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (Throwable var11) {
                        // 如果关闭输入流时出错,将错误附加到原始异常中
                        var12.addSuppressed(var11);
                    }
                }
                throw var12;
            }

            // 确保在正常解析结束后关闭输入流
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (IOException var13) {
            // 捕获 IO 异常,并抛出 BeanDefinitionStoreException,指明加载 XML 资源时出现 IO 错误
            throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var13);
        } finally {
            // 在 finally 块中,无论是否成功,都会移除当前加载的资源,防止内存泄漏
            currentResources.remove(encodedResource);

            // 如果当前资源集合为空,则移除该线程局部变量
            if (currentResources.isEmpty()) {
                this.resourcesCurrentlyBeingLoaded.remove();
            }
        }

        // 返回加载的 Bean 定义数量
        return var5;
    }
}

核心方法:var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
    try {
        // 调用 doLoadDocument 方法,将传入的 InputSource 和 Resource 转换为 Document 对象 (XML文档)
        Document doc = this.doLoadDocument(inputSource, resource);

        // 调用 registerBeanDefinitions 方法,将解析出的 Document 注册为 Bean 定义,返回已注册的 Bean 定义数量
        int count = this.registerBeanDefinitions(doc, resource);

        // 如果日志级别为 DEBUG,则记录已加载的 Bean 定义数量以及来源的资源信息
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Loaded " + count + " bean definitions from " + resource);
        }

        // 返回加载的 Bean 定义数量
        return count;

    } catch (BeanDefinitionStoreException var5) {
        // 如果抛出 BeanDefinitionStoreException,则直接重新抛出该异常
        throw var5;
    } catch (SAXParseException var6) {
        // 如果在解析 XML 文档时出现 SAX 解析异常,并且包含行号信息,抛出一个带有更详细错误信息的 XmlBeanDefinitionStoreException
        throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
    } catch (SAXException var7) {
        // 如果在解析 XML 过程中出现其他 SAX 异常,抛出 XmlBeanDefinitionStoreException,提示 XML 文档无效
        throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
    } catch (ParserConfigurationException var8) {
        // 如果出现解析器配置异常,抛出 BeanDefinitionStoreException,提示解析器配置错误
        throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
    } catch (IOException var9) {
        // 如果在解析过程中出现 IO 异常,抛出 BeanDefinitionStoreException,提示 IO 错误
        throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
    } catch (Throwable var10) {
        // 捕获所有其他未预料的异常,抛出 BeanDefinitionStoreException,提示解析过程中发生了意外的异常
        throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
    }
}

六、环境

Spring 提供的 Environment 接口是对应用程序运行环境的抽象,主要模拟了应用程序的两个核心部分:profilesproperties。这些功能帮助应用程序根据不同的环境条件或配置需求,动态地管理 bean 定义和应用程序的配置。

1. Profiles(配置分组)

  • Profile 是一种用于对 bean 定义进行分组的机制。我们可以根据应用程序的不同运行环境(如开发、测试、生产等)定义不同的 profile。
  • 一个 profile 包含一组特定的 bean 定义,这些 bean 只有在该 profile 被激活时才会被加载到 Spring 容器中。这种机制允许我们根据环境条件灵活地选择和加载不同的配置。

激活 profile 的方式:

  • application.propertiesapplication.yml 文件中指定:
spring.profiles.active=dev
  • 通过 JVM 启动参数指定:
-Dspring.profiles.active=prod
  • 编程方式动态设置:
`ConfigurableEnvironment environment = applicationContext.getEnvironment(); environment.setActiveProfiles("test");`

2. Properties(属性配置)

  • Properties 是应用程序中的一个重要概念,通常以 key-value 的形式存在,用来配置应用的各种参数。
  • 属性可以来自多种不同的来源,包括:
    • 属性文件(如 .properties.yaml 文件)
    • JVM 系统属性(如 -D 参数)
    • 系统环境变量
    • JNDI 属性
    • servlet 上下文参数
    • 自定义的 Properties 对象或 Map 对象

Spring 通过 Environment 对象为这些属性源提供了统一的访问接口。你可以通过 Environment 接口来获取这些属性,并应用到应用程序的不同部分。

获取属性的方式:

  • 使用 Environment 提供的 getProperty() 方法来解析属性:
Environment env = applicationContext.getEnvironment();
String dbUrl = env.getProperty("database.url");
  • 这种机制允许我们通过配置文件、环境变量等多种途径设置应用程序属性,并通过代码动态解析它们,从而大大增强了应用程序的可配置性和灵活性。

spring中尝试获取上下文环境,并输出环境变量:

// 创建一个通用的ApplicationContext容器
//创建一个通用的 `ApplicationContext` 实例,它是 Spring 框架的核心容器,负责加载和管理 beans。
ApplicationContext ctx = new GenericApplicationContext();

// 获取当前应用程序环境的Environment对象
// Environment提供了一系列方法,用于访问系统属性、环境变量和配置文件中的属性
Environment env = ctx.getEnvironment();

// 使用Environment对象的containsProperty()方法检查名为"JAVA_HOME"的属性是否存在
// "JAVA_HOME"通常是用于指定Java安装路径的环境变量
boolean containsMyProperty = env.containsProperty("JAVA_HOME");

// 通过Logger记录信息,输出是否存在名为"JAVA_HOME"的环境变量
// {}是占位符,后面的containsMyProperty值(true或false)会动态替换进去
Logger.info("Does my environment contain the 'JAVA_HOME' property? {}", containsMyProperty);

// 使用getProperty()方法获取"JAVA_HOME"属性的值
// 如果存在这个属性,它会返回实际值;如果不存在,返回null
Logger.info("The 'JAVA_HOME' is {}", env.getProperty("JAVA_HOME"));

这里的Environment的具体实现类是StandardEnvironment,我们自己尝试一下创建一个StandardEnvironment并添加属性:

// 创建一个 StandardEnvironment 实例,这是 Spring 的标准环境实现,包含系统环境变量和 JVM 属性等信息
StandardEnvironment env = new StandardEnvironment();

// 创建一个 Properties 对象,用于存储键值对形式的配置信息
Properties properties = new Properties();
properties.setProperty("age", "12");  // 设置键 "age" 的值为 "12"

// 将 Properties 对象封装为一个 PropertySource 对象,
// 其中 name 为 "my-propertySource",表示属性源的名字,第二个参数是 properties 对象
PropertySource<?> source = new PropertiesPropertySource("my-propertySource", properties);

// 获取当前环境对象的 PropertySources 集合,
// 这是一个可变的属性源集合,包含所有环境配置的属性源
MutablePropertySources propertySources = env.getPropertySources();

// 将我们创建的 PropertySource 添加到属性源集合的最后(addLast 表示追加到最后)
propertySources.addLast(source);

// 打印出在环境中查找属性 "age" 的值,应该输出 "12"
System.out.println(env.getProperty("age"));  // 输出: 12

@PropertySource 注解提供了一种声明性方式,可以将属性文件中的键值对添加到 Spring 环境(Environment)中。你可以通过这个注解将属性文件加载到 Spring 的上下文中,以便在应用程序中使用这些属性。

假设有一个名为 app.properties 的文件,内容如下:

teacherName=itnanls

编写配置类:

@Configuration
@PropertySource("classpath:app.properties")  // 加载类路径下的 app.properties 文件
public class AppConfiguration {
    // 这里可以定义更多的配置内容或 Bean
}

测试类:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(classes = AppConfiguration.class)  // 指定 Spring Boot 测试环境,加载 AppConfiguration 类
public class PropertySourceTest {

    @Autowired
    Environment environment;  // 注入 Spring 的 Environment,用于访问属性

    @Test
    public void testEnv() {
        // 从 Environment 中获取 "teacherName" 属性的值,并输出到控制台
        String teacherName = environment.getProperty("teacherName");
        System.out.println(teacherName);
        
        // 断言属性值是否为 "itnanls"
        assertEquals("itnanls", teacherName);
    }
}

七、发布订阅

1. 概述

Spring 提供的 事件多播器(Event Multicaster),是一种实现发布-订阅模式的机制。它能够帮助开发者在应用程序中轻松地广播事件,使得事件可以被多个监听器接收并处理。这种模式与组播(multicast)类似,即消息只会在需要时复制,确保消息传递的效率。

在这里插入图片描述

在 Spring 框架中,事件机制是基于观察者设计模式实现的。通过使用 SimpleApplicationEventMulticaster,我们可以轻松地发布事件并注册监听器,响应这些事件。这种机制适用于事件驱动的开发方式,可以让组件之间解耦,同时确保各个监听器能独立地处理事件。

实现监听器:

import org.springframework.context.ApplicationListener;

public class EmailListener implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent event) {
        // 处理事件,例如发送邮件
        System.out.println("Email sent form: " + event.getSource());
    }
}

public class MessageListener implements ApplicationListener<OrderEvent> {
    @Override
    public void onApplicationEvent(OrderEvent event) {
        // 处理事件,例如发送消息
        System.out.println("Message sent form: " + event.getSource());
    }
}

定义事件类:

import org.springframework.context.ApplicationEvent;

public class OrderEvent extends ApplicationEvent {
    public OrderEvent(Object source) {
        super(source);
    }

    @Override
    public String toString() {
        return "OrderEvent triggered!";
    }
}

测试方法:

@Test
public void testEventMulticaster() {
    // 创建一个简单的事件多播器 SimpleApplicationEventMulticaster 实例
    SimpleApplicationEventMulticaster caster = new SimpleApplicationEventMulticaster();
    
    // 为事件多播器添加监听器,这些监听器将会处理事件
    caster.addApplicationListener(new EmailListener());   // 添加 EmailListener
    caster.addApplicationListener(new MessageListener()); // 添加 MessageListener
    
    // 模拟触发事件,向所有注册的监听器广播一个 OrderEvent 事件
    caster.multicastEvent(new OrderEvent(this));  // `this` 代表事件源
}

2. 源码阅读

这其中有很多复杂的情况,比如listener是我们直接手动注册的实例呢,还是spring工厂 中的bean呢,如果是bean是singleton还是prototype呢?

因为源码比较复杂,我们需要结合下图一起看:
(即发布了事件要进行实例化的过程)
![[Pasted image 20241105160206.png]]

listener被调用执行后,如何进行了缓存:
![[Pasted image 20241105160315.png]]

Spring 的事件多播器在广播事件时,会缓存已解析的事件类型和监听器列表,以加速重复事件的广播。spring提供了一个retrieverCache缓存,其key[Event+Source]value是已解析的监听器列表,其中单例、非单例、编程式的分别进行存储:

  • 编程式的listener和单例的listener bean存储在一起
  • 非单例的bean存储在一个集合中

查看addApplicationListener源码:

public void addApplicationListener(ApplicationListener<?> listener) {
    // 使用 synchronized 关键字对 defaultRetriever 进行同步,以确保线程安全
    synchronized(this.defaultRetriever) {
        
        // 尝试获取 listener 的单例目标对象
        Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
        
        // 如果 singletonTarget 是 ApplicationListener 的实例
        if (singletonTarget instanceof ApplicationListener) {
            // 从 applicationListeners 列表中移除 singletonTarget,以防重复添加
            this.defaultRetriever.applicationListeners.remove(singletonTarget);
        }

        // 将 listener 添加到 applicationListeners 列表中
        this.defaultRetriever.applicationListeners.add(listener);
        
        // 清空 retrieverCache 缓存,确保新的监听器配置能及时生效
        this.retrieverCache.clear();
    }
}

查看其核心方法this.defaultRetriever.applicationListeners.add(listener);

查看this.defaultRetriever的相关代码:

private class DefaultListenerRetriever {
    // 用于存储已注册的 ApplicationListener 实例的集合,确保唯一性和顺序
    public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
    
    // 用于存储监听器的 Bean 名称,延迟加载这些 Bean
    public final Set<String> applicationListenerBeans = new LinkedHashSet<>();

    // 私有构造函数,限制实例化方式
    private DefaultListenerRetriever() {
    }

    /**
     * 获取所有注册的 ApplicationListener 实例,包括直接注册的监听器实例和通过 bean 名称注册的监听器。
     * @return 返回 ApplicationListener 实例的集合,按照顺序和优先级排列。
     */
    public Collection<ApplicationListener<?>> getApplicationListeners() {
        // 创建一个列表,用于存放所有的监听器,大小为已注册的实例数量与 Bean 名称数量之和
        List<ApplicationListener<?>> allListeners = new ArrayList<>(this.applicationListeners.size() + this.applicationListenerBeans.size());
        
        // 将直接添加的监听器实例加入到 allListeners 列表中
        allListeners.addAll(this.applicationListeners);

        // 如果 applicationListenerBeans 不为空,说明存在通过 Bean 名称注册的监听器
        if (!this.applicationListenerBeans.isEmpty()) {
            // 获取 BeanFactory,以便通过 Bean 名称加载监听器实例
            BeanFactory beanFactory = AbstractApplicationEventMulticaster.this.getBeanFactory();
            
            // 遍历 applicationListenerBeans 集合
            Iterator<String> var3 = this.applicationListenerBeans.iterator();
            while(var3.hasNext()) {
                String listenerBeanName = var3.next();

                try {
                    // 根据 Bean 名称获取 ApplicationListener 实例
                    ApplicationListener<?> listener = (ApplicationListener<?>) beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    
                    // 如果该监听器不在 allListeners 列表中,则添加,避免重复
                    if (!allListeners.contains(listener)) {
                        allListeners.add(listener);
                    }
                } catch (NoSuchBeanDefinitionException var6) {
                    // 捕获 NoSuchBeanDefinitionException 异常,若该 Bean 名称不存在则忽略
                }
            }
        }

        // 使用 AnnotationAwareOrderComparator 对所有监听器进行排序,确保监听器按优先级顺序执行
        AnnotationAwareOrderComparator.sort(allListeners);
        
        // 返回包含所有监听器的集合
        return allListeners;
    }
}

接下来注册事件multicastEvent的源码:

public void multicastEvent(ApplicationEvent event) {
    // 调用重载方法 multicastEvent,传入 event 和 null,null 表示使用事件默认的类型
    this.multicastEvent(event, (ResolvableType)null);
}

public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
    // 如果 eventType 不为空,使用 eventType;否则根据事件实例确定事件类型
    ResolvableType type = eventType != null ? eventType : ResolvableType.forInstance(event);

    // 获取任务执行器,用于异步执行监听器方法
    Executor executor = this.getTaskExecutor();
    
    // 获取与事件类型匹配的监听器,并进行迭代
    Iterator<ApplicationListener<?>> var5 = this.getApplicationListeners(event, type).iterator();

    // 循环遍历所有监听器,依次调用它们
    while(var5.hasNext()) {
        // 获取当前监听器
        ApplicationListener<?> listener = var5.next();

        // 如果存在执行器且监听器支持异步执行
        if (executor != null && listener.supportsAsyncExecution()) {
            try {
                // 使用执行器异步调用监听器的处理方法
                executor.execute(() -> {
                    this.invokeListener(listener, event);
                });
            } catch (RejectedExecutionException var8) {
                // 如果任务被拒绝(执行器可能满载),则直接同步执行监听器
                this.invokeListener(listener, event);
            }
        } else {
            // 如果执行器不可用或监听器不支持异步执行,则同步调用监听器
            this.invokeListener(listener, event);
        }
    }
}

再往invokeListener去细看,最后其实就是调用listener.onApplicationEvent(event);方法

但我们更关注其缓存的过程,因此回到multicastEvent方法中的获取监听器方法getApplicationListeners(event, type)

protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
    // 获取事件的来源对象
    Object source = event.getSource();
    
    // 获取来源对象的类型(如果来源对象不为空)
    Class<?> sourceType = source != null ? source.getClass() : null;
    
    // 创建一个监听器缓存键,用于缓存监听器的查询结果,缓存键包含事件类型和来源类型(Key)
    AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
    
    // 用于存储新创建的缓存检索器(Value)
    AbstractApplicationEventMulticaster.CachedListenerRetriever newRetriever = null;
    
    // 从缓存中获取已有的缓存检索器
    AbstractApplicationEventMulticaster.CachedListenerRetriever existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.get(cacheKey);
    
    // 如果缓存中没有找到对应的检索器,并且类型信息是安全的(可缓存)
    if (existingRetriever == null && (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
        // 创建一个新的 CachedListenerRetriever,用于缓存该事件的监听器集合
        newRetriever = new AbstractApplicationEventMulticaster.CachedListenerRetriever();
        
        // 尝试将新创建的缓存检索器放入缓存中,如果已经有相同键的缓存检索器则返回已有检索器
        existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
        
        // 如果 existingRetriever 不为空,说明缓存中已有同键的缓存检索器,将 newRetriever 置为空
        if (existingRetriever != null) {
            newRetriever = null;
        }
    }

    // 如果 existingRetriever 不为空且其缓存的监听器集合存在,直接返回该集合
    if (existingRetriever != null) {
        Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
        if (result != null) {
            return result;
        }
    }

    // 如果缓存中没有结果,调用 retrieveApplicationListeners 方法检索并返回事件监听器集合
    return this.retrieveApplicationListeners(eventType, sourceType, newRetriever);
}

查看兜底方法this.retrieveApplicationListeners(eventType, sourceType, newRetriever)

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
    ResolvableType eventType, 
    @Nullable Class<?> sourceType, 
    @Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever) {

    // 创建一个列表 allListeners,用于存储所有符合条件的监听器
    List<ApplicationListener<?>> allListeners = new ArrayList<>();
    // 如果 retriever 不为空,创建一个过滤后的监听器集合,用于后续缓存
    Set<ApplicationListener<?>> filteredListeners = retriever != null ? new LinkedHashSet<>() : null;
    // 同样为 retriever 创建一个过滤后的监听器 Bean 集合,用于后续缓存
    Set<String> filteredListenerBeans = retriever != null ? new LinkedHashSet<>() : null;

    LinkedHashSet<ApplicationListener<?>> listeners;
    LinkedHashSet<String> listenerBeans;

    // 从默认检索器 defaultRetriever 中获取所有监听器和监听器 Bean
    synchronized(this.defaultRetriever) {
        listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
        listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
    }

    // 遍历所有的监听器对象
    Iterator<ApplicationListener<?>> var9 = listeners.iterator();
    while (var9.hasNext()) {
        ApplicationListener<?> listener = var9.next();
        // 检查当前监听器是否支持当前事件类型和来源类型
        if (this.supportsEvent(listener, eventType, sourceType)) {
            // 如果 retriever 不为空,将支持的监听器加入过滤后的监听器集合
            if (retriever != null) {
                filteredListeners.add(listener);
            }
            // 将支持的监听器加入到总的监听器列表
            allListeners.add(listener);
        }
    }

    // 如果存在监听器 Bean
    if (!listenerBeans.isEmpty()) {
        // 获取 Spring 的 BeanFactory 实例
        ConfigurableBeanFactory beanFactory = this.getBeanFactory();
        Iterator<String> var17 = listenerBeans.iterator();

        while (var17.hasNext()) {
            String listenerBeanName = var17.next();

            try {
                // 检查当前监听器 Bean 是否支持当前事件类型
                if (this.supportsEvent(beanFactory, listenerBeanName, eventType)) {
                    // 获取该监听器 Bean 的实例
                    ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    // 获取监听器的原始对象(用于处理代理对象)
                    ApplicationListener<?> unwrappedListener = (ApplicationListener<?>) AopProxyUtils.getSingletonTarget(listener);

                    // 如果监听器是代理对象且其原始对象存在于缓存中,将原始对象替换为代理对象
                    if (listener != unwrappedListener) {
                        if (filteredListeners != null && filteredListeners.contains(unwrappedListener)) {
                            filteredListeners.remove(unwrappedListener);
                            filteredListeners.add(listener);
                        }
                        if (allListeners.contains(unwrappedListener)) {
                            allListeners.remove(unwrappedListener);
                            allListeners.add(listener);
                        }
                    }

                    // 如果该监听器不在总的监听器列表中,并且支持当前事件类型,添加到相应集合中
                    if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
                        if (retriever != null) {
                            // 如果 Bean 是单例,将其放入 filteredListeners,否则放入 filteredListenerBeans
                            if (beanFactory.isSingleton(listenerBeanName)) {
                                filteredListeners.add(listener);
                            } else {
                                filteredListenerBeans.add(listenerBeanName);
                            }
                        }
                        allListeners.add(listener);
                    }
                } else {
                    // 如果不支持当前事件类型,从缓存和总监听器列表中移除
                    Object listener = beanFactory.getSingleton(listenerBeanName);
                    if (retriever != null) {
                        filteredListeners.remove(listener);
                    }
                    allListeners.remove(listener);
                }
            } catch (NoSuchBeanDefinitionException var14) {
                // 捕获没有定义该 Bean 的异常,跳过当前 Bean
            }
        }
    }

    // 对总的监听器列表进行排序,确保监听器的执行顺序
    AnnotationAwareOrderComparator.sort(allListeners);

    // 如果 retriever 不为空,将过滤后的结果保存到缓存中
    if (retriever != null) {
        if (filteredListenerBeans.isEmpty()) {
            retriever.applicationListeners = new LinkedHashSet<>(allListeners);
            retriever.applicationListenerBeans = filteredListenerBeans;
        } else {
            retriever.applicationListeners = filteredListeners;
            retriever.applicationListenerBeans = filteredListenerBeans;
        }
    }

    // 返回所有支持的监听器集合
    return allListeners;
}

第三章 容器和上下文

使用容器的优势主要包括以下几个方面:

  1. 统一管理
    使用容器需要遵循统一的规范,例如 Jakarta Servlet 6.0 规范、Spring 6 规范等。这些规范帮助我们编写标准化的容器内容(如 servlet、bean),便于统一管理容器内内容的生命周期。规范化的管理可以确保组件之间的兼容性和稳定性,减少维护成本。

  2. 隔离应用
    容器可以隔离应用程序与底层复杂性,使开发者能够专注于业务逻辑的开发。理论上,我们不需要关心容器是如何启动的,如何建立连接等细节。容器封装了这些底层实现,开发者可以将更多的精力投入到实际的业务实现上,而无需关注底层技术实现。

  3. 分层管理
    容器的设计通常分层清晰,每个层次有明确的职责划分。例如,MVC 框架中的容器与 Spring 的容器是不同的,但它们之间又能相互关联。这样的分层设计保证了职责的分离,使各层之间的边界清晰,便于管理和扩展,提升了系统的可维护性和模块化程度。

一、认识bean工厂

bean工厂是我们spring容器的载体, 是spring 上下文的主要内容。下图展示了我们整个beanI厂的常见的接口和类以及功能,其中我们需要注意几点:

  1. 不同的接口展现了不同的能力,是对子类能力的抽象
  2. 抽象类构建通用方法的实现,是通用核心方法(模板方法)的具体实现
  3. 具体类完成特定功能的实现,是特定功能的具体实现

有了这样的思想,我们才能更好的区阅读源码:

![[Pasted image 20241109134138.png]]

  • ListablebeanFactory接口:更强的枚举能力
  • AutowireCapableBeanFactory接口:自动装配的能力
  • HierachiclBeanFactory接口:分层的能力
    以上三个接口可组成一个复合接口:ConfigurableListableBeanFactory接口

1、基础能力

public interface BeanFactory {
    // 定义一个工厂Bean的前缀常量,通常用于区分FactoryBean类型的实例
    String FACTORY_BEAN_PREFIX = "&";

    // 根据Bean名称获取Bean实例
    Object getBean(String var1) throws BeansException;

    // 根据Bean名称和类型获取Bean实例
    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    // 根据Bean名称和构造参数获取Bean实例
    Object getBean(String var1, Object... var2) throws BeansException;

    // 根据类型获取Bean实例
    <T> T getBean(Class<T> var1) throws BeansException;

    // 根据类型和构造参数获取Bean实例
    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    // 获取Bean的ObjectProvider,用于延迟获取Bean实例
    <T> ObjectProvider<T> getBeanProvider(Class<T> var1);

    // 根据ResolvableType获取Bean的ObjectProvider
    <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);

    // 检查容器中是否包含指定名称的Bean
    boolean containsBean(String var1);

    // 判断Bean是否为单例模式
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;

    // 判断Bean是否为原型模式(即每次请求都会创建新实例)
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    // 判断Bean的类型是否匹配指定的ResolvableType
    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    // 判断Bean的类型是否匹配指定的Class类型
    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;

    // 获取指定Bean的类型(返回Class对象),如果Bean不存在则返回null
    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    // 获取指定Bean的类型,并指定是否初始化FactoryBean的实现类
    @Nullable
    Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;

    // 获取指定Bean名称的所有别名
    String[] getAliases(String var1);
}

上面源码有提到ObjectProvider,什么是ObjectProvider

ObjectProvider继承自ObjectFactory

@FunctionalInterface
public interface ObjectFactory<T> {
	/*
	*这个方法用于创建并返回对象。
	*如果在创建过程中出现问题(例如无法创建对象),会抛出 BeansException异常。
	**/
    T getObject() throws BeansException;
}

ObjectFactory目的就是为了屏蔽复杂逻辑,直接创建对象。
如:

ObjectFactory<User> factory = () -> {
    // 通过某种逻辑生成 User,甚至可以生成代理对象
    return new Random().nextInt(100) > 50 ? 
        new User("tom", 12) : 
        new User("alice", 25);
};

但我们在获取时,不用关注具体逻辑。直接User user = factory.getObject();获取即可

查看ObjectProvider源码:

public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {

    // 获取容器中的一个对象实例,支持传入额外的参数进行构造函数注入
    T getObject(Object... var1) throws BeansException;

    // 如果容器中有可用的对象,返回该对象;如果没有,返回 null
    @Nullable
    T getIfAvailable() throws BeansException;

	…………

    // 获取容器中唯一的对象实例,如果有多个符合条件的 Bean,返回 null
    @Nullable
    T getIfUnique() throws BeansException;
	…………
}

ObjectProvider 允许 Spring 用户在运行时动态获取 Bean,并且可以选择性地提供默认值或者执行某些操作。它为按需获取和条件判断提供了多种方法,是 Spring 的灵活依赖注入的一部分。

小插曲:

ObjectProvider是为了解决隐式注入时产生的问题而提出的概念
spring4.3之前,我们的bean如果需要使用特定构造器进行构造时必须使用@Autowired注解

在 Spring 中,通常通过构造函数注入来传递依赖项:

@Service
public class UserService {
    private UserDao userDao;

    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}

在上面的代码中,UserService 依赖于 UserDao,并通过构造函数注入 UserDao 实例。在 Spring 容器启动时,UserDao ,否则会抛出 NoSuchBeanDefinitionException

当 Spring 容器中没有 UserDao 的实例,或者有多个 UserDao 实例时,构造函数注入将会失败,抛出类似以下的异常:

Parameter 0 of constructor in com.yd1class.UserService required a bean of type 'com.yd1class.UserDao' that could not be found.

ObjectProvider 可以用来处理可选的或唯一的 Bean 依赖。在这种情况下,如果 UserDao 不可用或不唯一,ObjectProvider 会提供一个懒加载的方式来获取 UserDao,并能够优雅地处理这种情况

@Service
public class UserService {
    private UserDao userDao;

    public UserService(ObjectProvider<UserDao> userDao) {
        // 使用 getIfAvailable() 或 getIfUnique() 来获取 UserDao 实例
        this.userDao = userDao.getIfUnique();
    }
}

在这个例子中,ObjectProvider<UserDao> 用于替代直接注入 UserDaoObjectProvider 提供了多种方法来处理 Bean 的获取:

  • getIfAvailable():如果容器中有 UserDao 实例且没有冲突,则返回它。如果没有实例,则返回 null
  • getIfUnique():如果容器中有唯一的 UserDao 实例,则返回它。如果存在多个实例,则返回 null

2、更强大的枚举能力

public interface ListableBeanFactory extends BeanFactory {
    // 判断是否包含指定名称的Bean定义
    boolean containsBeanDefinition(String var1);

    // 获取Bean定义的数量
    int getBeanDefinitionCount();

    // 获取所有Bean定义的名称
    String[] getBeanDefinitionNames();

    // 获取指定类型的Bean的ObjectProvider,可选择包含非单例或懒加载的Bean
    <T> ObjectProvider<T> getBeanProvider(Class<T> var1, boolean var2);

    // 根据ResolvableType获取指定类型的Bean的ObjectProvider,可选择包含非单例或懒加载的Bean
    <T> ObjectProvider<T> getBeanProvider(ResolvableType var1, boolean var2);

    // 根据ResolvableType获取指定类型的Bean名称数组
    String[] getBeanNamesForType(ResolvableType var1);

    // 根据ResolvableType获取指定类型的Bean名称数组,可选择是否包含非单例或懒加载的Bean
    String[] getBeanNamesForType(ResolvableType var1, boolean var2, boolean var3);

    // 获取指定类型的Bean名称数组(通过Class类型)
    String[] getBeanNamesForType(@Nullable Class<?> var1);

    // 获取指定类型的Bean名称数组,可选择是否包含非单例或懒加载的Bean(通过Class类型)
    String[] getBeanNamesForType(@Nullable Class<?> var1, boolean var2, boolean var3);

    // 获取指定类型的所有Bean实例及其名称,返回Map
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> var1) throws BeansException;

    // 获取指定类型的所有Bean实例及其名称,可选择是否包含非单例或懒加载的Bean,返回Map
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> var1, boolean var2, boolean var3) throws BeansException;

    // 获取带有指定注解类型的Bean名称数组
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> var1);

    // 获取带有指定注解类型的所有Bean实例及其名称,返回Map
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> var1) throws BeansException;

    // 在指定的Bean上查找指定类型的注解
    @Nullable
    <A extends Annotation> A findAnnotationOnBean(String var1, Class<A> var2) throws NoSuchBeanDefinitionException;
}

3、灵活的分层能力

分层的能力十分重要,这在web工程里有典型应用,spring和springmvc会建 立两个独立的上下文,后续涉及web工程时我们再深入讲解,分层之后各司其职,更易管理:

public interface HierarchicalBeanFactory extends BeanFactory {
    // 获取父级的BeanFactory,如果存在的话
    @Nullable
    BeanFactory getParentBeanFactory();

    // 忽略祖先上下文定义的bean,检查本地工厂中是否包含指定名称的本地Bean定义
    boolean containsLocalBean(String var1);
}

4、构建和自动装配的能力

这个接口的实现及其复杂,主要是赋予子类自动装配的能力,是容器最核心的接口,这个接口定义了bean的创建以及装配能力,同时细粒度的控制了bean的生命周期:

public interface AutowireCapableBeanFactory extends BeanFactory {
    // 自动装配的常量,用于指示不同的自动装配模式
    int AUTOWIRE_NO = 0;                 // 不自动装配
    int AUTOWIRE_BY_NAME = 1;            // 根据名称自动装配
    int AUTOWIRE_BY_TYPE = 2;            // 根据类型自动装配
    int AUTOWIRE_CONSTRUCTOR = 3;        // 使用构造器进行自动装配
    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;         // 自动检测自动装配模式(已废弃)
    String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL"; // 用于标识原始实例的后缀

    // 创建给定类的新Bean实例,并应用所有的后处理器
    <T> T createBean(Class<T> var1) throws BeansException;

    // 自动装配现有的Bean实例,将Spring管理的Bean属性注入该实例
    void autowireBean(Object var1) throws BeansException;

    // 配置现有的Bean实例,将其与容器中的其他组件连接起来
    Object configureBean(Object var1, String var2) throws BeansException;

    // 按照指定的自动装配类型创建Bean实例
    Object createBean(Class<?> var1, int var2, boolean var3) throws BeansException;

    // 根据给定的类型和自动装配模式装配一个新的实例
    Object autowire(Class<?> var1, int var2, boolean var3) throws BeansException;

    // 自动装配Bean的属性
    void autowireBeanProperties(Object var1, int var2, boolean var3) throws BeansException;

    // 将Bean定义中的属性值应用到现有的Bean实例上
    void applyBeanPropertyValues(Object var1, String var2) throws BeansException;

    // 初始化Bean实例
    Object initializeBean(Object var1, String var2) throws BeansException;

    // 应用Bean的初始化前置处理器
    Object applyBeanPostProcessorsBeforeInitialization(Object var1, String var2) throws BeansException;

    // 应用Bean的初始化后置处理器
    Object applyBeanPostProcessorsAfterInitialization(Object var1, String var2) throws BeansException;

    // 销毁指定的Bean实例
    void destroyBean(Object var1);

    // 解析指定类型的Bean,并返回一个包含名称的Bean实例持有者
    <T> NamedBeanHolder<T> resolveNamedBean(Class<T> var1) throws BeansException;

    // 根据名称解析依赖关系
    Object resolveBeanByName(String var1, DependencyDescriptor var2) throws BeansException;

    // 解析给定的依赖关系
    @Nullable
    Object resolveDependency(DependencyDescriptor var1, @Nullable String var2) throws BeansException;

    // 解析依赖关系,同时允许指定依赖名称集合和类型转换器
    @Nullable
    Object resolveDependency(DependencyDescriptor var1, @Nullable String var2, @Nullable Set<String> var3, @Nullable TypeConverter var4) throws BeansException;
}

5、更强的配置能力

这个bean工厂接口并不用于正常的应用程序代码中。这个扩展接口只是为了允许框架内部的即插即用和对beanI厂配置方法的特殊访问,具体如下:

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    // 范围常量,定义了常见的 bean 生命周期
    String SCOPE_SINGLETON = "singleton";
    String SCOPE_PROTOTYPE = "prototype";

    // 设置父 BeanFactory
    void setParentBeanFactory(BeanFactory var1) throws IllegalStateException;

    // 配置加载 bean 的类加载器
    void setBeanClassLoader(@Nullable ClassLoader var1);
    @Nullable ClassLoader getBeanClassLoader();

    void setTempClassLoader(@Nullable ClassLoader var1);
    @Nullable ClassLoader getTempClassLoader();

    // 配置 bean 元数据的缓存
    void setCacheBeanMetadata(boolean var1);
    boolean isCacheBeanMetadata();

    // 设置和获取自定义的 BeanExpressionResolver,处理 bean 定义中的表达式
    void setBeanExpressionResolver(@Nullable BeanExpressionResolver var1);
    @Nullable BeanExpressionResolver getBeanExpressionResolver();

    // 设置和获取自定义的 ConversionService,处理类型转换
    void setConversionService(@Nullable ConversionService var1);
    @Nullable ConversionService getConversionService();

    // 注册自定义的属性编辑器,并将其复制到 PropertyEditorRegistry 中
    void addPropertyEditorRegistrar(PropertyEditorRegistrar var1);
    void registerCustomEditor(Class<?> var1, Class<? extends PropertyEditor> var2);
    void copyRegisteredEditorsTo(PropertyEditorRegistry var1);

    // 配置和获取 TypeConverter,用于处理 bean 属性转换
    void setTypeConverter(TypeConverter var1);
    TypeConverter getTypeConverter();

    // 注册和解析 bean 定义中的嵌入式值
    void addEmbeddedValueResolver(StringValueResolver var1);
    boolean hasEmbeddedValueResolver();
    @Nullable String resolveEmbeddedValue(String var1);

    // 添加和管理 BeanPostProcessor,在初始化前后应用
    void addBeanPostProcessor(BeanPostProcessor var1);
    int getBeanPostProcessorCount();

    // 注册和获取自定义的作用域
    void registerScope(String var1, Scope var2);
    String[] getRegisteredScopeNames();
    @Nullable Scope getRegisteredScope(String var1);

    // 设置和获取 ApplicationStartup,用于跟踪应用程序启动过程
    void setApplicationStartup(ApplicationStartup var1);
    ApplicationStartup getApplicationStartup();

    // 获取 AccessControlContext,用于保障 bean 创建和访问的安全性
    AccessControlContext getAccessControlContext();

    // 复制来自其他 ConfigurableBeanFactory 的配置
    void copyConfigurationFrom(ConfigurableBeanFactory var1);

    // 管理 bean 的别名
    void registerAlias(String var1, String var2) throws BeanDefinitionStoreException;
    void resolveAliases(StringValueResolver var1);

    // 获取合并后的 bean 定义,处理覆盖和继承问题
    BeanDefinition getMergedBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

    // 判断一个 bean 是否是 FactoryBean 类型
    boolean isFactoryBean(String var1) throws NoSuchBeanDefinitionException;

    // 设置和检查 bean 是否正在创建中
    void setCurrentlyInCreation(String var1, boolean var2);
    boolean isCurrentlyInCreation(String var1);

    // 管理 bean 之间的依赖关系
    void registerDependentBean(String var1, String var2);
    String[] getDependentBeans(String var1);
    String[] getDependenciesForBean(String var1);

    // 销毁指定的 bean 实例和处理作用域中的 bean
    void destroyBean(String var1, Object var2);
    void destroyScopedBean(String var1);

    // 销毁所有单例 bean
    void destroySingletons();
}

6、工厂的生命周期

bean工厂的生命周期比较简单: start->onRefresh-> Running->onClose->stop
每一个生命周期节点都会完成大量的工作,我们后边的内容会详细介绍:

public interface Lifecycle {
    void start();  // 启动方法,启动组件或服务
    void stop();   // 停止方法,停止组件或服务
    boolean isRunning();  // 判断当前组件或服务是否处于运行状态
}
public interface LifecycleProcessor extends Lifecycle {
    /**
     * 上下文刷新通知,例如自动启动组件。
     * 当上下文刷新时,会触发此方法,通常用于自动启动与上下文相关的组件或服务。
     */
    void onRefresh(); 

    /**
     * 上下文关闭阶段的通知,例如自动停止组件。
     * 当上下文关闭时,会触发此方法,通常用于自动停止与上下文相关的组件或服务。
     */
    void onClose();
}

二、bean工厂的创建

一个典型的功能强大的bean工厂实现,就是DefaultListableBeanFactory, 事实上我们的容器中维护的beanFactory都是这个类的实例;

我们看一下该类的类图:
在这里插入图片描述

这里简单的总结一下, 一个完整的bean工厂应该具备哪些能力?

  1. bean工厂的基础能力,枚举bean,分层,自动装配、独立配置等。
  2. 注册单例bean (包括Factorybean) 的能力。
  3. 注册别名的能力。

尝试使用一下bean工厂

// 创建一个 Bean 工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

// 注册 Bean 定义,beanName 为 "user"
factory.registerBeanDefinition("user", beanDefinition);

// 创建一个实例化策略,使用 Cglib 实现子类化来创建实例
InstantiationStrategy strategy = new CglibSubclassingInstantiationStrategy();

// 使用策略实例化 Bean
Object user = strategy.instantiate(beanDefinition, "user", factory);

// 输出实例化后的 Bean 信息
logger.info("user --> {}", user);

查看实例化strategy.instantiate源码:

这个 instantiate 方法用于通过无参构造函数实例化一个 Bean。如果没有需要覆盖的方法,它将使用默认构造函数来创建实例;否则,会调用带有方法注入的实例化方式。

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // 如果没有方法覆盖,直接使用构造函数实例化
    if (!bd.hasMethodOverrides()) {
        Constructor constructorToUse;
        // 同步块,确保在多线程环境中安全地解析构造函数
        synchronized(bd.constructorArgumentLock) {
            // 获取已解析的构造函数或工厂方法
            constructorToUse = (Constructor) bd.resolvedConstructorOrFactoryMethod;
            // 如果构造函数还未解析,进行解析
            if (constructorToUse == null) {
                Class<?> clazz = bd.getBeanClass();
                // 如果指定的类是接口,则抛出异常,因为接口无法直接实例化
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    // 处理安全管理器,若存在,则在受保护的环境中访问构造函数
                    if (System.getSecurityManager() != null) {
                        clazz.getClass();  // 获取类的字节码对象
                        constructorToUse = (Constructor) AccessController.doPrivileged(() -> {
                            return clazz.getDeclaredConstructor();
                        });
                    } else {
                        // 无安全管理器的情况下直接获取默认构造函数
                        constructorToUse = clazz.getDeclaredConstructor();
                    }
                    // 将解析后的构造函数缓存到 Bean 定义中,以后可以直接使用
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                } catch (Throwable ex) {
                    // 如果没有找到默认构造函数,抛出实例化异常
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        // 使用 BeanUtils 实例化对象,传入解析的构造函数和空参数
        return BeanUtils.instantiateClass(constructorToUse, new Object[0]);
    } else {
        // 否则,使用带方法注入的实例化方式
        return this.instantiateWithMethodInjection(bd, beanName, owner);
    }
}

其中的方法覆盖是指:(了解即可)

  • lookup-method注入:
    lookup-method注入是spring动态改变bean里方法的实现。指定方法的返回值为某个已经存在的bean。
  • replaced-method注入:
    replaced- method注入是spring动态改变bean方法的-种实现。他可以改变的方法执行逻辑,将方法进行替换,定义替换方法的类(需要继承接口org.springframework.beans.factory.support.MethodReplacer)接口。

FactoryBean

通常用来帮我们去创建一些复杂对象,屏蔽复杂对象的创建过程,如将复杂的创建逻辑隐藏在getObject()方法中

  • 能够将getObject()方法返回的bean(默认是单例的)注册到容器中
  • 也会将自身注册到容器中,想获取FactoryBean需要在名字前面加&
public interface FactoryBean<T> {
    // 用于标识 FactoryBean 中生成对象的类型属性名
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    /**
     * 获取由此 FactoryBean 管理的对象实例。
     * @return 由此 FactoryBean 创建的对象实例
     * @throws Exception 如果创建过程出错
     */
    @Nullable
    T getObject() throws Exception;

    /**
     * 获取 FactoryBean 管理的对象类型。
     * @return FactoryBean 创建的对象类型
     */
    @Nullable
    Class<?> getObjectType();

    /**
     * 判断此 FactoryBean 创建的对象是否为单例。
     * 默认返回 true,表示 FactoryBean 管理的对象为单例。
     * @return 如果此 FactoryBean 创建的对象为单例,则返回 true,否则返回 false
     */
    default boolean isSingleton() {
        return true;
    }
}

尝试使用FactoryBean:

@Component("user")
public class UserFactoryBean implements FactoryBean<User> {
    
    /**
     * 创建并返回 User 实例。
     * 这里可以包含复杂的创建逻辑,帮助我们生成复杂的对象。
     * @return User对象实例
     * @throws Exception 如果对象创建过程中出现问题
     */
    @Override
    public User getObject() throws Exception {
        // 可能包含复杂的逻辑,生成一个 User 实例
        return new User("it", 30);
    }

    /**
     * 返回 FactoryBean 管理的对象类型。
     * 在此情况下,返回 User.class 类型。
     * @return User.class
     */
    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

测试类

Object user = beanFactory . getBean( name: "user") ;
object userFactory = beanFactory . getBean( name: "&user");
Logger. info("user -->{} ” ,user);
Logger. info("userFactory -->{} " , userFactory);

三、了解扩展点

spring给我们提供了很多的扩展点,这些扩展点可以允许我们在spring上下文启动的任意环节进行干预,实现自己的逻辑。大致将spring的启动环节画一个图,当然他可能不准确,我们只是想将大致的环节勾勒出来,然后看看其中的可以打展的地方。

在这里插入图片描述

其中比较重要的是beanFactory的后置处理操作和bean的后置处理操作

后置处理器:
在某些节点提供一些钩子函数,用于扩展,可以干预整个spring工厂的启动

这些方法会在特定的时间由框架进行主动调用,并把beanFactory返回

实现BeanFactoryPostProcessor接口,实现BeanFactory后置处理器:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 在Spring容器初始化时,调用此方法对BeanFactory进行自定义处理
        System.out.println("beanFactory ------------->" + beanFactory);
    }
}

实现BeanPostProcessor接口,实现堆Bean创建后置处理器:

@Component
// 自定义 BeanPostProcessor 实现类
public class MyBeanPostProcessor implements BeanPostProcessor {

    // 在 Bean 初始化前执行的方法
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " --------------> postProcessBeforeInitialization");
        return bean;  // 返回 Bean 本身,以便 Spring 继续初始化流程
    }

    // 在 Bean 初始化后执行的方法
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " --------------> postProcessAfterInitialization");
        return bean;  // 返回 Bean 本身或包装后的 Bean
    }
}

四、认识ApplicationContext

ApplicationContext是应用程序的中央接口,提供一些便利的功能, 引导Spring的程序进行启动,他是我们学习spring中的重中之重,理解了ApplicationContext我们就学会了spring。

spring上下文提供了丰富的功能,拥有强大的能力,于切的spring的知识内其实都是为了服务一个ApplicationContext, 下图展示了Springpplication中的一些核心接口和类:

在这里插入图片描述

一个ApplicationContext继承了五个接口,共同为一个上下文赋能,这些接口我们都已经接触过了:

  1. EnvironmentCapable:提供一个上下文环境的能力
  2. ListableBeanFactory:枚举bean工厂的bean的能力
  3. HierarchicalBeanFactory:分层的能力
  4. MessageSource:国际化的能力
  5. ApplicationEventPublisher:发布事件的能力
// ApplicationContext接口是Spring框架的核心接口之一,它代表应用的上下文容器,负责管理Bean及其生命周期。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

    // 获取ApplicationContext的唯一ID。
    @Nullable
    String getId();

    // 获取应用的名称。
    String getApplicationName();

    // 获取ApplicationContext的显示名称,通常用于调试和日志。
    String getDisplayName();

    // 获取应用启动时间(时间戳),表示容器启动的时间。
    long getStartupDate();

    // 获取当前应用上下文的父上下文,如果没有则返回null。
    @Nullable
    ApplicationContext getParent();

    // 获取AutowireCapableBeanFactory,用于执行自动装配和实例化Bean的相关操作。
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

其子接口ConfigurableApplicationContextApplicationContext进行了扩展:

// ConfigurableApplicationContext接口扩展了ApplicationContext接口,提供了额外的配置方法,
// 允许在运行时对ApplicationContext进行动态调整和管理。
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {

    // 配置文件路径的分隔符常量,支持逗号、分号、空格和换行符。
    String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
    
    // 重要的Bean名称常量,包括转换服务、加载时间编织器、环境配置等。
    String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
    String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
    String ENVIRONMENT_BEAN_NAME = "environment";
    String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
    String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
    String APPLICATION_STARTUP_BEAN_NAME = "applicationStartup";
    String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";

    // 设置ApplicationContext的唯一ID。
    void setId(String var1);

    // 设置当前上下文的父上下文。
    void setParent(@Nullable ApplicationContext var1);

    // 设置用于环境配置的ConfigurableEnvironment对象。
    void setEnvironment(ConfigurableEnvironment var1);

    // 获取ConfigurableEnvironment实例,用于访问和配置环境属性。
    ConfigurableEnvironment getEnvironment();

    // 设置应用启动对象,用于记录启动阶段的性能信息。
    void setApplicationStartup(ApplicationStartup var1);

    // 获取应用启动对象。
    ApplicationStartup getApplicationStartup();

    // 向上下文中添加BeanFactory后置处理器。
    void addBeanFactoryPostProcessor(BeanFactoryPostProcessor var1);

    // 向上下文添加应用监听器,用于处理事件。
    void addApplicationListener(ApplicationListener<?> var1);

    // 设置类加载器。
    void setClassLoader(ClassLoader var1);

    // 添加协议解析器,用于自定义资源解析。
    void addProtocolResolver(ProtocolResolver var1);

    // 初始化或刷新上下文,加载或重建所有Bean的定义和实例。
    void refresh() throws BeansException, IllegalStateException;

    // 注册关闭钩子,以确保在JVM关闭时执行上下文的关闭操作。
    void registerShutdownHook();

    // 关闭ApplicationContext,释放资源。
    void close();

    // 检查上下文是否处于活跃状态。
    boolean isActive();

    // 获取可配置的BeanFactory,允许自定义Bean创建逻辑。
    ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}

举几个例子,理解里面的函数:

  1. 实现了一个自定义容器类 MyGenericApplicationContext,继承自 GenericApplicationContext,并重写了 registerShutdownHook() 方法。
    这个方法中注册了一个线程,当 JVM 关闭时,这个线程会被自动调用来执行资源清理或其他关闭操作。
// 自定义应用上下文类,继承自 GenericApplicationContext
public class MyGenericApplicationContext extends GenericApplicationContext {

    // 关闭钩子线程对象,用于在容器关闭时执行清理操作
    private Thread shutdownHook = null;

    @Override
    public void registerShutdownHook() {
        // 检查是否已有关闭钩子线程被注册
        if (this.shutdownHook == null) {
            // 创建一个新的关闭钩子线程并命名
            this.shutdownHook = new Thread("SHUTDOWN_HOOK_THREAD_NAME") {
                @Override
                public void run() {
                    // 关闭钩子线程的运行逻辑
                    System.out.println("容器关闭了,该干啥干啥吧!");
                }
            };
            // 将该线程注册为 JVM 的关闭钩子线程
            Runtime.getRuntime().addShutdownHook(this.shutdownHook);
        }
    }
}
  1. 加载配置文件并获取bean
// 创建 GenericApplicationContext 实例,并设置资源位置
GenericApplicationContext myGenericApplicationContext = new GenericXmlApplicationContext("classpath:config-file.xml");

// 获取 TeddyDog 类型的 Bean 实例
TeddyDog bean = myGenericApplicationContext.getBean(TeddyDog.class);

// 记录获取到的 Bean 信息
logger.info("dog ----> {}", bean);

接下来我们查看上下文容器的构建过程,先查看new GenericXmlApplicationContext();源码:

public GenericXmlApplicationContext(String... resourceLocations) {
    // 加载指定路径的资源文件,并解析其中定义的 Bean
    this.load(resourceLocations);  
    
    // 刷新上下文,以便完成 Bean 的初始化工作
    this.refresh();  
}

load()其实就是调用loadBeanDefinitions(),这个之前有说过。

当调用GenericXmlApplicationContext构造时,会调用父类GenericApplicationContext的无参构造:

public GenericApplicationContext() {
    // 标志是否使用自定义的类加载器,初始化为 false,表示默认不使用
    this.customClassLoader = false;
    
    // 使用原子布尔类型来标识上下文是否已刷新,初始状态为未刷新
    this.refreshed = new AtomicBoolean();
    
    // 创建一个默认的 Bean 工厂实例,用于管理和配置 Bean 的生命周期
    this.beanFactory = new DefaultListableBeanFactory();
}

可以看到在定义上下文的时候就会帮我们创建了一个BeanFactory

Bean工厂本身就是一个注册器,因此load()后会将BeandeFinition扫描并注册到bean工厂中。

紧接着下一个步骤就是:refresh()刷新容器

第四章 刷新容器

我们看到的任何构建applicationContext的过程都是两步走:

  1. 收集元数据
  2. 刷新容器.
    刷新容器的核心目的就是实例化我们的容器和容器内的bean,这是spring最核心的地方,没有之一。
    容器几乎所有的工作都会在这个时间段完成,但是有一个前提就是就是此时所有的元数据搜集工作应该完成,相应的beanDefinition已经准备好了, 保存在DefaultlistableBeanFactorymap中:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);

查看AbstractApplicationContextrefresh()方法源码:

public void refresh() throws BeansException, IllegalStateException {
    // 加锁,防止在多线程环境中重复刷新
    synchronized (this.startupShutdownMonitor) {
        // 启动一个监测步骤,用于记录上下文刷新过程(不重要)
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // 准备刷新过程(如初始化环境变量、检查环境配置等)
        this.prepareRefresh();

        // 获取一个新的 BeanFactory 实例,进行配置和管理 Bean
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

        // 配置 BeanFactory,设置一些标准的容器属性和预配置
        this.prepareBeanFactory(beanFactory);

        try {
            // 提供对 BeanFactory 的后置处理(扩展点)
            this.postProcessBeanFactory(beanFactory);

            // 启动记录 Bean 后置处理步骤
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

            // 调用 BeanFactory 的后处理器(如修改 Bean 定义,添加其他 Bean)
            this.invokeBeanFactoryPostProcessors(beanFactory);

            // 注册 BeanPostProcessor,用于对 Bean 实例进行额外操作
            this.registerBeanPostProcessors(beanFactory);

            // 结束 Bean 后置处理的监测步骤
            beanPostProcess.end();

            // 初始化消息源(用于国际化消息处理)
            this.initMessageSource();

            // 初始化事件广播器(用于在容器中分发事件)
            this.initApplicationEventMulticaster();

            // 具体的刷新操作(如在子类中添加额外的初始化)
            this.onRefresh();

            // 注册监听器,确保能够响应容器事件
            this.registerListeners();

            // 完成 Bean 的初始化(最关键的,完成所有非懒加载的单例bean)
            this.finishBeanFactoryInitialization(beanFactory);

            // 完成刷新操作
            this.finishRefresh();

        } catch (BeansException ex) {
            // 捕获异常,记录警告信息并取消刷新
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + ex);
            }

            // 销毁已创建的 Bean,释放资源
            this.destroyBeans();

            // 取消刷新操作,清除相关状态
            this.cancelRefresh(ex);

            // 抛出异常,以便调用方处理
            throw ex;

        } finally {
            // 重置缓存,清理一些通用资源
            this.resetCommonCaches();

            // 结束刷新监测步骤
            contextRefresh.end();
        }
    }
}

this.finishBeanFactoryInitialization(beanFactory);完成 Bean 的初始化(最关键的,完成所有非懒加载的单例bean)

  • 对于单例bean,其生命周期由spring容器来管理
  • 非单例bean,spring只管生,不管死。其资源的回收由JVM来管理

大概步骤:
1.准备刷新➡2.获得一个新鲜的bean工厂➡3.为bean工厂做一些前期的准备➡4.留给子类做后置处理的函数➡5.调用bean工厂的后置处理器➡6.注册bean的后置处理器➡7.初始化消息源➡8.初始化多播器➡9.onRefresh()留给子类作为刷新时的扩展点➡10.注册listener➡11.注册非懒加载的单例bean➡12.完成刷新

若失败:
1.销毁所有的bean➡2.取消刷新

无论失败与否:
1.清除缓存➡2.标记刷新结束

1、准备刷新:prepareRefresh源码

此方法在 Spring 容器刷新之前进行一些初始化和验证操作,为容器的启动做准备。

protected void prepareRefresh() {
    // 设置启动时间为当前时间,用于后续的统计和监控
    this.startupDate = System.currentTimeMillis();

    // 更新容器状态,标记为已开启且未关闭
    this.closed.set(false);
    this.active.set(true);

    // 记录调试日志,输出刷新操作开始的信息
    if (this.logger.isDebugEnabled()) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Refreshing " + this);
        } else {
            this.logger.debug("Refreshing " + this.getDisplayName());
        }
    }

    // 初始化属性源,用于子类扩展方法配置属性源(例如加载环境变量等)
    this.initPropertySources();

    // 校验环境变量,确保所有必需的属性已设置
    this.getEnvironment().validateRequiredProperties();

    // 初始化早期事件监听器集合
    if (this.earlyApplicationListeners == null) {
        // 若首次刷新,记录当前的事件监听器
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    } else {
        // 若不是首次刷新,清空并重置为初始监听器集合
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // 初始化早期应用事件集合,用于存储在刷新期间的事件,便于后续统一处理
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

该函数主要做的事情:

  • initPropertySources用于加载并初始化属性源
  • validateRequiredProperties校验属性是否为空
  • 初始化早期事件监听器集合

initPropertySources用于加载并初始化属性源(键值对),说明环境已经准备好了。

那么环境是什么时候准备好的,该抽象类中提供了两个方法:
如果环境不存在则新new一个StandardEnvironment

/**
 * 获取当前的环境对象,如果环境对象为空,则创建并初始化一个新的标准环境。
 * @return 当前应用上下文的环境对象
 */
public ConfigurableEnvironment getEnvironment() {
    // 检查环境对象是否为 null,如果是则调用 createEnvironment() 方法创建新实例
    if (this.environment == null) {
        this.environment = this.createEnvironment();
    }

    // 返回环境对象
    return this.environment;
}

/**
 * 创建一个新的 ConfigurableEnvironment 实例。
 * 可在子类中重写以提供自定义的环境配置。
 * @return 新的标准环境对象
 */
protected ConfigurableEnvironment createEnvironment() {
    // 返回标准的 ConfigurableEnvironment 实现
    return new StandardEnvironment();
}

继续查看initPropertySources()具体实现的源码:

/**
 * 初始化属性源,将环境对象中的属性源进行配置。
 * 如果当前环境是 Web 环境(ConfigurableWebEnvironment),则进行 Web 环境的初始化。
 */
protected void initPropertySources() {
    // 获取当前环境对象
    ConfigurableEnvironment env = this.getEnvironment();

    // 如果当前环境是 Web 环境,则进行 Web 环境的属性源初始化
    if (env instanceof ConfigurableWebEnvironment) {
        // 将 servletContext 传递给 ConfigurableWebEnvironment 的 initPropertySources 方法
        ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, (ServletConfig) null);
    }
}

进一步查看initPropertySources源码,

/**
 * 初始化 Web 环境下的属性源。
 * 通过调用 WebApplicationContextUtils 的 initServletPropertySources 方法,初始化与 servletContext 和 servletConfig 相关的属性源。
 *
 * @param servletContext 当前应用的 ServletContext,提供 Web 应用的上下文信息。
 * @param servletConfig 当前应用的 ServletConfig,提供 Servlet 配置信息。
 */
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
    // 调用 WebApplicationContextUtils 的 initServletPropertySources 方法初始化属性源
    WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
}

进一步看initServletPropertySources源码:

/**
 * 初始化 Servlet 环境中的属性源,将 ServletContext 和 ServletConfig 中的初始化参数添加到 Spring 环境的属性源中。
 *
 * @param sources Spring 环境中的属性源集合。
 * @param servletContext 当前应用的 ServletContext,提供 Web 应用的上下文信息。
 * @param servletConfig 当前应用的 ServletConfig,提供 Web 应用的初始化配置信息。
 */
public static void initServletPropertySources(MutablePropertySources sources, @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
    // 确保 sources 不为 null
    Assert.notNull(sources, "'propertySources' must not be null");

    // 处理 ServletContext 中的初始化参数
    String name = "servletContextInitParams";
    if (servletContext != null && sources.get(name) instanceof StubPropertySource) {
        // 如果 ServletContext 不为 null 且对应的属性源是 StubPropertySource,则替换成新的 ServletContextPropertySource
        sources.replace(name, new ServletContextPropertySource(name, servletContext));
    }

    // 处理 ServletConfig 中的初始化参数
    name = "servletConfigInitParams";
    if (servletConfig != null && sources.get(name) instanceof StubPropertySource) {
        // 如果 ServletConfig 不为 null 且对应的属性源是 StubPropertySource,则替换成新的 ServletConfigPropertySource
        sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
    }
}

上面的代码主要做的是将name="servletContextInitParams"name = "servletConfigInitParams"进行替换,并设置到spring中去

因此initPropertySources()是一个扩展点,Web容器的上下文会在该方法中进行一些初始化的操作,将serverlet容器里的两个配置添加到环境中,将spring上下文和servlet上下文做勾连。

2、获得一个新鲜的bean工厂:obtainFreshBeanFactory源码

ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();

进一步查看:

/**
 * 获取一个新的、已刷新的 BeanFactory 实例。
 * 
 * @return 刷新后的 ConfigurableListableBeanFactory 实例。
 */
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 刷新 BeanFactory
    this.refreshBeanFactory();
    
    // 返回当前的 BeanFactory 实例
    return this.getBeanFactory();
}

查看具体实现类GenericApplicationContext是怎么获取beanFactory的:

public final ConfigurableListableBeanFactory getBeanFactory() {  
    return this.beanFactory;  
}

这个beanFactory在空参构造的时候就会给我们构建好:

public GenericApplicationContext() {  
    this.customClassLoader = false;  
    this.refreshed = new AtomicBoolean();  
    this.beanFactory = new DefaultListableBeanFactory();  
}

查看GenericApplicationContextrefreshBeanFactory方法:

/**
 * 刷新 BeanFactory,确保只进行一次刷新操作。
 * 
 * @throws IllegalStateException 如果尝试进行多次刷新,则抛出异常。
 */
protected final void refreshBeanFactory() throws IllegalStateException {
    // 使用 AtomicBoolean 来确保只执行一次刷新操作
    if (!this.refreshed.compareAndSet(false, true)) {
        // 如果 refreshed 为 true,表示已经进行了刷新,抛出异常
        throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    } else {
        // 设置 BeanFactory 的序列化 ID
        this.beanFactory.setSerializationId(this.getId());
    }
}

由上述代码可知道,BeanFactory只支持一次刷新。

AbstractRefreshableApplicationContext该实现类的beanFactory是支持多次刷新的

3、为bean工厂做一些前期的准备:prepareBeanFactory(beanFactory)

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置 BeanClassLoader,指定类加载器,用于加载 Bean 类
    beanFactory.setBeanClassLoader(this.getClassLoader());

    // 如果不应该忽略 SpEL(Spring 表达式语言),则设置表达式解析器
    if (!shouldIgnoreSpel) {
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    }

    // 添加自定义的属性编辑器注册器,用于处理特定类型的属性转换
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));

    // 向 BeanFactory 中添加一个 Bean 后处理器,处理应用上下文相关的处理
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    // 忽略一些与环境相关的接口,这意味着这些接口将不会被自动注入
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

    // 注册一些可解析的依赖关系,允许在 Bean 中注入这些接口的实例
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 添加一个新的 Bean 后处理器,用于检测应用事件监听器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 如果不是在原生镜像中,并且 BeanFactory 中包含名为 "loadTimeWeaver" 的 Bean,则添加一个新的后处理器
    if (!NativeDetector.inNativeImage() && beanFactory.containsBean("loadTimeWeaver")) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 如果 BeanFactory 中没有名为 "environment" 的 Bean,则注册一个单例 Bean
    if (!beanFactory.containsLocalBean("environment")) {
        beanFactory.registerSingleton("environment", this.getEnvironment());
    }

    // 如果 BeanFactory 中没有名为 "systemProperties" 的 Bean,则注册一个单例 Bean
    if (!beanFactory.containsLocalBean("systemProperties")) {
        beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
    }

    // 如果 BeanFactory 中没有名为 "systemEnvironment" 的 Bean,则注册一个单例 Bean
    if (!beanFactory.containsLocalBean("systemEnvironment")) {
        beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
    }

    // 如果 BeanFactory 中没有名为 "applicationStartup" 的 Bean,则注册一个单例 Bean
    if (!beanFactory.containsLocalBean("applicationStartup")) {
        beanFactory.registerSingleton("applicationStartup", this.getApplicationStartup());
    }
}
  • 这段代码的作用是配置 beanFactory 忽略对特定接口的依赖注入。也就是说,当某个 bean 实现了这些接口时,Spring 容器不会自动将对应的资源注入到这些 bean 中,而是会忽略它们的依赖注入。这在某些情况下可以防止不必要的依赖注入,从而提升性能或避免复杂的依赖链。
beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
  • beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    忽略了以上的资源,但是需要在特定时间去调用并设置这些资源类。ApplicationContextAwareProcessor中提供了一个函数:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 检查 bean 是否实现了指定的 Aware 接口
    // 如果没有实现这些接口,直接返回 bean,不做进一步处理
    if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && 
        !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && 
        !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware) && 
        !(bean instanceof ApplicationStartupAware)) {
        return bean;
    } else {
        // 初始化访问控制上下文,用于在安全受限环境中进行权限控制
        AccessControlContext acc = null;
        if (System.getSecurityManager() != null) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        // 如果存在安全上下文,在其权限控制下调用 invokeAwareInterfaces 方法
        if (acc != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareInterfaces(bean);
                return null;
            }, acc);
        } else {
            // 否则直接调用 invokeAwareInterfaces 方法
            this.invokeAwareInterfaces(bean);
        }

        // 返回处理后的 bean
        return bean;
    }
}

进一步看invokeAwareInterfaces

private void invokeAwareInterfaces(Object bean) {
    // 如果 bean 实现了 EnvironmentAware 接口,注入 Environment 实例
    if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    }

    // 如果 bean 实现了 EmbeddedValueResolverAware 接口,注入 EmbeddedValueResolver 实例
    if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }

    // 如果 bean 实现了 ResourceLoaderAware 接口,注入 ResourceLoader 实例(这里是 applicationContext)
    if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }

    // 如果 bean 实现了 ApplicationEventPublisherAware 接口,注入 ApplicationEventPublisher 实例
    if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    }

    // 如果 bean 实现了 MessageSourceAware 接口,注入 MessageSource 实例
    if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }

    // 如果 bean 实现了 ApplicationStartupAware 接口,注入 ApplicationStartup 实例
    if (bean instanceof ApplicationStartupAware) {
        ((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
    }

    // 如果 bean 实现了 ApplicationContextAware 接口,注入 ApplicationContext 实例
    if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
}
  • 下面这段代码注册了可解析的依赖关系。
// 注册一些可解析的依赖关系,允许在 Bean 中注入这些接口的实例
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this)

如果某个 bean 的构造函数或字段需要注入 BeanFactoryResourceLoaderApplicationEventPublisherApplicationContext,那么 Spring 容器就能自动提供这些依赖。

  • beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    该处是添加一个后置处理器ApplicationListenerDetector,该类是一个监听器,能够帮我们探测哪些beanlistener,并帮我们注册到多播器中
public Object postProcessAfterInitialization(Object bean, String beanName) {
    // 检查当前 Bean 是否实现了 ApplicationListener 接口
    if (bean instanceof ApplicationListener) {
        
        // 从 singletonNames 中获取 beanName 对应的 Boolean 值,
        // 表示该 Bean 是否是单例 (singleton)。
        Boolean flag = (Boolean) this.singletonNames.get(beanName);
        
        // 如果该 Bean 是单例 (flag 为 true),则将其注册为事件监听器
        if (Boolean.TRUE.equals(flag)) {
            this.applicationContext.addApplicationListener((ApplicationListener)bean);
        } 
        
        // 如果不是单例 (flag 为 false)
        else if (Boolean.FALSE.equals(flag)) {
            // 如果是非单例并且没有在容器中注册该 Bean 时,输出警告日志
            if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
                logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface but is not reachable for event multicasting by its containing ApplicationContext because it does not have singleton scope. Only top-level listener beans are allowed to be of non-singleton scope.");
            }

            // 移除非单例监听器 Bean 的名称,防止后续重复注册
            this.singletonNames.remove(beanName);
        }
    }

    // 返回处理后的 Bean(未做修改的 Bean)
    return bean;
}

4、留给子类做后置处理的函数

// 提供对 BeanFactory 的后置处理(扩展点)
this.postProcessBeanFactory(beanFactory);

// 调用 BeanFactory 的后处理器(如修改 Bean 定义,添加其他 Bean)
this.invokeBeanFactoryPostProcessors(beanFactory);

这两个函数在功能上类似,但是还是存在一些区别:

  1. postProcessBeanFactory(beanFactory)

    • 目的:提供一个对 BeanFactory 进行自定义修改的扩展点。
    • 调用者:通常是框架的具体实现类,例如 AbstractApplicationContext
  2. invokeBeanFactoryPostProcessors(beanFactory)

    • 目的:调用所有注册的 BeanFactoryPostProcessor 实现类。
    • 调用者:由 Spring 框架自动调用。

postProcessBeanFactory(beanFactory)一般是框架的开发者写的,invokeBeanFactoryPostProcessors(beanFactory)一般是spring使用的开发人员写的。

查看postProcessBeanFactory(beanFactory)的一个具体实现:

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	//检查当前 `ApplicationContext` 是否有一个有效的 `ServletContext`(即当前环境是否为 Web 环境)。如果不在 Web 环境下,`servletContext` 可能为空。
    if (this.servletContext != null) {
	    //添加了一个 `ServletContextAwareProcessor` 后置处理器。`ServletContextAwareProcessor` 是一个 `BeanPostProcessor`,专门用于处理实现了 `ServletContextAware` 接口的 Bean。它会将 `ServletContext` 注入到实现了 `ServletContextAware` 接口的 Bean 中,使这些 Bean 能够访问到 Web 应用的 `ServletContext`。
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
	    //告知 `BeanFactory`,对于实现了 `ServletContextAware` 接口的 Bean,自动装配时忽略 `ServletContextAware` 接口。因为依赖注入已经由 `ServletContextAwareProcessor` 负责处理,所以在这里忽略它可以避免重复注入。
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    }
	// 注册 Web 应用特有的作用域,比如 request 和 session 作用域
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    // 将 Web 环境中的特殊 Bean(如 ServletContext)注册到 beanFactory 中 
    // 使得其他组件可以通过依赖注入直接访问这些 Bean
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}

5、调用bean工厂的后置处理器

查看invokeBeanFactoryPostProcessors源码:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {  
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());  
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {  
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));  
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));  
    }  
  
}

主要看第一行代码PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    // 用于记录已经处理过的 Bean 名称,避免重复处理
    Set<String> processedBeans = new HashSet();
    ArrayList<BeanFactoryPostProcessor> regularPostProcessors;
    ArrayList<BeanDefinitionRegistryPostProcessor> registryProcessors;

    // 如果 beanFactory 是 BeanDefinitionRegistry 的实例(常见于可注册 Bean 的环境)
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        regularPostProcessors = new ArrayList<>();
        registryProcessors = new ArrayList<>();

        // 分类传入的 PostProcessor 列表
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                // 如果是 BeanDefinitionRegistryPostProcessor,调用其注册处理方法
                ((BeanDefinitionRegistryPostProcessor) postProcessor).postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add((BeanDefinitionRegistryPostProcessor) postProcessor);
            } else {
                // 如果是普通的 BeanFactoryPostProcessor
                regularPostProcessors.add(postProcessor);
            }
        }

        // 处理 BeanDefinitionRegistryPostProcessor
        ArrayList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
        // 获取所有注册的 BeanDefinitionRegistryPostProcessor 类型的 Bean
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

        // 按 PriorityOrdered 排序并调用
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();

        // 按 Ordered 排序并调用
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();

        // 最后调用所有剩余未排序的 BeanDefinitionRegistryPostProcessor
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();
        }

        // 调用所有处理后的 BeanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        // 如果不是 BeanDefinitionRegistry,只处理普通的 BeanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 获取 BeanFactoryPostProcessor 类型的 Bean 名称
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    regularPostProcessors = new ArrayList<>();
    registryProcessors = new ArrayList<>();
    currentRegistryProcessors = new ArrayList<>();

    // 分类剩余的 BeanFactoryPostProcessor 并根据优先级处理
    for (String ppName : postProcessorNames) {
        if (!processedBeans.contains(ppName)) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                regularPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                registryProcessors.add(ppName);
            } else {
                currentRegistryProcessors.add(ppName);
            }
        }
    }

    // 按优先级排序并调用所有剩余的 PostProcessor
    sortPostProcessors(regularPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

    // 处理 Ordered 类型的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(registryProcessors.size());
    for (String postProcessorName : registryProcessors) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // 调用无序的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(currentRegistryProcessors.size());
    for (String ppName : currentRegistryProcessors) {
        nonOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // 清除元数据缓存以确保 Bean 定义的完整性
    beanFactory.clearMetadataCache();
}

什么是BeanDefinitionRegistryPostProcessor

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {  
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;  
}

BeanDefinitionRegistryPostProcessor 是 Spring 框架中的一个接口,它扩展了 BeanFactoryPostProcessor 接口。与 BeanFactoryPostProcessor 不同的是,BeanDefinitionRegistryPostProcessor 可以在 Spring 容器加载 Bean 之前,进一步自定义和修改 Bean 的定义信息。其主要特点是能够访问 BeanDefinitionRegistry,因此可以动态注册、修改或移除 BeanDefinition(即 Bean 的定义信息)。

BeanDefinitionRegistryPostProcessor 主要包括以下两个方法:

  1. postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
    用于在所有 Bean 定义被加载但尚未初始化时修改或注册 BeanDefinition。通过传入的 BeanDefinitionRegistry 对象,可以动态地注册、修改或删除 BeanDefinition
  2. postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
    继承自 BeanFactoryPostProcessor,用于在 BeanFactory 实例化所有单例 Bean 前,修改 BeanFactory 的设置。这个方法更倾向于整体 BeanFactory 的配置,而非单个 BeanDefinition

PostProcessor可以PriorityOrderedOrdered来实现优先级调用或者调用次序。

大致流程总结:

  1. 首先执行 BeanDefinitionRegistryPostProcessor
  • 按照 PriorityOrdered 优先级排序并执行。
  • 按照 Ordered 优先级排序并执行。
  • 处理无序的 BeanDefinitionRegistryPostProcessor
  • 递归检查是否有新的处理器需要执行。
  1. 然后执行普通的 BeanFactoryPostProcessor
  • 按照 PriorityOrdered 排序并执行。
  • 按照 Ordered 排序并执行。
  • 执行没有优先级的 BeanFactoryPostProcessor
  1. 最后清除元数据缓存,以确保 BeanDefinition 处理的完整性。

6、注册bean的后置处理器

registerBeanPostProcessors源码:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {  
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);  
}

继续深入查看:

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    // 获取所有 BeanPostProcessor 类型的 Bean 名称
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    
    // 计算目标 BeanPostProcessor 数量
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    
    // 为 BeanFactory 添加一个检查器,用于确保 BeanPostProcessor 注册正确
    beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    
    // 创建不同类型的 BeanPostProcessor 列表
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); // 存储 PriorityOrdered 类型的 BeanPostProcessor
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); // 存储 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor
    List<String> orderedPostProcessorNames = new ArrayList<>(); // 存储 Ordered 类型的 BeanPostProcessor 名称
    List<String> nonOrderedPostProcessorNames = new ArrayList<>(); // 存储没有排序的 BeanPostProcessor 名称

    // 遍历所有 BeanPostProcessor,进行分类
    for (int var10 = 0; var10 < postProcessorNames.length; ++var10) {
        String ppName = postProcessorNames[var10];
        
        // 如果是 PriorityOrdered 类型,加入 priorityOrderedPostProcessors
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = (BeanPostProcessor) beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            
            // 如果是 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor,加入 internalPostProcessors
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        } 
        // 如果是 Ordered 类型,加入 orderedPostProcessorNames
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        } 
        // 如果没有实现排序接口,则加入 nonOrderedPostProcessorNames
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 对 PriorityOrdered 类型的 BeanPostProcessor 进行排序并注册
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // 对 Ordered 类型的 BeanPostProcessor 进行处理
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = (BeanPostProcessor) beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        
        // 如果是 MergedBeanDefinitionPostProcessor 类型的,加入 internalPostProcessors
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }

    // 对 Ordered 类型的 BeanPostProcessor 进行排序并注册
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // 对没有排序的 BeanPostProcessor 进行处理
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = (BeanPostProcessor) beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        
        // 如果是 MergedBeanDefinitionPostProcessor 类型的,加入 internalPostProcessors
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }

    // 注册没有排序的 BeanPostProcessor
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 对 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor 进行排序并注册
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // 最后,注册 ApplicationListenerDetector,它用于检测并注册实现了 ApplicationListener 的 Bean
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

这里涉及到MergedBeanDefinitionPostProcessor,这是BeanDefinitionPostProcessor的一个子接口:

  • Bean生命周期的第一步就是合并Bean的定义
  • MergedBeanDefinitionPostProcessor 是 Spring 框架中的一个接口,它继承自 BeanPostProcessor,主要用于在 Bean 定义合并之后、Bean 实例化之前对 Bean 定义进行修改。

有个小细节:
在第一次遍历时,PriorityOrdered类型的BeanDefinitionPostProcessor会实例化然后加到链表中;而其它类型的加到链表中的是它们的名字,待后续进行遍历实例化。
这是为了按顺序进行实例化

注册的过程比较简单,就是拿到Bean工厂然后注册进去:

private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    // 判断 beanFactory 是否是 AbstractBeanFactory 的实例
    if (beanFactory instanceof AbstractBeanFactory) {
        // 如果是 AbstractBeanFactory,则直接使用 addBeanPostProcessors 批量注册 BeanPostProcessor
        ((AbstractBeanFactory) beanFactory).addBeanPostProcessors(postProcessors);
    } else {
        // 如果不是 AbstractBeanFactory,逐个遍历 postProcessors 列表,逐个注册 BeanPostProcessor
        Iterator var2 = postProcessors.iterator();

        while (var2.hasNext()) {
            // 获取当前的 BeanPostProcessor
            BeanPostProcessor postProcessor = (BeanPostProcessor) var2.next();
            // 注册到 beanFactory 中
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }
}

注:这里仅是注册,并未调用

7.初始化消息源➡8.初始化多播器➡9.onRefresh()

初始化消息initMessageSource消息:

protected void initMessageSource() {
    // 获取当前 BeanFactory,用于从中获取/注册 Bean
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();

    // 检查 BeanFactory 中是否已经存在名为 "messageSource" 的 Bean
    if (beanFactory.containsLocalBean("messageSource")) {
        // 如果存在,获取该 "messageSource" Bean,并转换为 MessageSource 类型
        this.messageSource = (MessageSource) beanFactory.getBean("messageSource", MessageSource.class);

        // 如果当前 messageSource 是 HierarchicalMessageSource 类型,并且父级 MessageSource 为空
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            // 将 messageSource 的父 MessageSource 设置为内部父级 MessageSource
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                hms.setParentMessageSource(this.getInternalParentMessageSource());
            }
        }

        // 如果日志级别为 TRACE,输出调试日志,显示正在使用的 messageSource
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Using MessageSource [" + this.messageSource + "]");
        }
    } else {
        // 如果 BeanFactory 中没有名为 "messageSource" 的 Bean,创建一个 DelegatingMessageSource 实例
        DelegatingMessageSource dms = new DelegatingMessageSource();
        // 设置 DelegatingMessageSource 的父级 MessageSource
        dms.setParentMessageSource(this.getInternalParentMessageSource());
        this.messageSource = dms;

        // 将新的 messageSource 注册为 BeanFactory 中的单例 bean
        beanFactory.registerSingleton("messageSource", this.messageSource);

        // 如果日志级别为 TRACE,输出调试日志,显示创建并使用的新 messageSource
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("No 'messageSource' bean, using [" + this.messageSource + "]");
        }
    }
}

初始化多播器:

protected void initApplicationEventMulticaster() {
    // 获取当前的 BeanFactory,用于从中获取或注册 Bean
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();

    // 检查 BeanFactory 中是否存在名为 "applicationEventMulticaster" 的 Bean
    if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
        // 如果存在,获取该 Bean 并转换为 ApplicationEventMulticaster 类型
        this.applicationEventMulticaster = (ApplicationEventMulticaster) beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
        
        // 如果日志级别为 TRACE,输出调试日志,显示正在使用的 applicationEventMulticaster
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    } else {
        // 如果 BeanFactory 中没有名为 "applicationEventMulticaster" 的 Bean,创建一个 SimpleApplicationEventMulticaster 实例
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);

        // 将新的 applicationEventMulticaster 注册为 BeanFactory 中的单例 Bean
        beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
        
        // 如果日志级别为 TRACE,输出调试日志,说明没有找到 "applicationEventMulticaster" Bean,因此创建了一个新的实例
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("No 'applicationEventMulticaster' bean, using [" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}

OnFresh()查看其一个具体子类的实现:

protected void onRefresh() {  
    super.onRefresh();  
  
    try {  
        this.createWebServer();  
    } catch (Throwable var2) {  
        throw new ApplicationContextException("Unable to start web server", var2);  
    }  
}

其在对单例的bean实例化之前,创建了一个WebServer

private void createWebServer() {
    // 获取当前 Web 服务器实例
    WebServer webServer = this.webServer;
    
    // 获取当前的 ServletContext
    ServletContext servletContext = this.getServletContext();

    // 如果 webServer 为 null 且 servletContext 也为 null(通常是第一次启动时)
    if (webServer == null && servletContext == null) {
        // 开始记录启动的步骤
        StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
        
        // 获取 Web 服务器工厂,这个工厂负责创建 Web 服务器
        ServletWebServerFactory factory = this.getWebServerFactory();
        
        // 给启动步骤添加标签,记录工厂类型
        createWebServer.tag("factory", factory.getClass().toString());
        
        // 通过工厂创建 Web 服务器,并使用 `ServletContextInitializer` 来初始化服务器
        this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});
        
        // 结束记录启动步骤
        createWebServer.end();
        
        // 注册 `WebServerGracefulShutdownLifecycle` 生命周期处理器用于优雅关机
        this.getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer));
        
        // 注册 `WebServerStartStopLifecycle` 生命周期处理器,用于启动和停止 Web 服务器
        this.getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer));
    }
    // 如果已经有 ServletContext,调用初始化方法
    else if (servletContext != null) {
        try {
            // 调用自定义的 ServletContext 初始化方法
            this.getSelfInitializer().onStartup(servletContext);
        } catch (ServletException var5) {
            // 捕获 ServletException 异常并抛出为 ApplicationContextException
            throw new ApplicationContextException("Cannot initialize servlet context", var5);
        }
    }

    // 初始化属性源(如配置文件、环境变量等)
    this.initPropertySources();
}

在创建WebServer工厂时,可以获得不同的Server工厂:

在这里插入图片描述

因此,在Onfresh()中会帮我们启动Tomcat服务器

10、注册listener

protected void registerListeners() {
    // 获取应用的监听器列表并遍历
    Iterator var1 = this.getApplicationListeners().iterator();

    while (var1.hasNext()) {
        // 获取每个应用事件监听器
        ApplicationListener<?> listener = (ApplicationListener)var1.next();
        // 将监听器添加到应用事件多播器中
        this.getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 获取所有类型为 ApplicationListener 的 bean 名称
    String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
    String[] var7 = listenerBeanNames;
    int var3 = listenerBeanNames.length;

    // 遍历这些 bean 名称并将对应的监听器添加到应用事件多播器中
    for (int var4 = 0; var4 < var3; ++var4) {
        String listenerBeanName = var7[var4];
        // 添加监听器 bean
        this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 获取早期的应用事件(如果有的话)
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    // 将 earlyApplicationEvents 置为 null,防止重复处理
    this.earlyApplicationEvents = null;

    // 如果有早期的应用事件,则广播它们
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        Iterator var9 = earlyEventsToProcess.iterator();

        while (var9.hasNext()) {
            // 获取每个早期事件
            ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
            // 将事件广播出去
            this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

11、注册非懒加载的单例bean

finishBeanFactoryInitialization(beanFactory)注意做的是实例化单例bean,是比较核心的方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 如果 BeanFactory 中存在名为 "conversionService" 的 Bean 且类型为 ConversionService,则将该 ConversionService 设置为当前 BeanFactory 的 ConversionService
    if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
        beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
    }

    // 如果 BeanFactory 尚未配置嵌入式值解析器(embedded value resolver),则添加一个解析器,用于解析嵌入的占位符(例如,${...})
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver((strVal) -> {
            return this.getEnvironment().resolvePlaceholders(strVal);  // 使用环境中的配置解析占位符
        });
    }

    // 获取所有实现了 LoadTimeWeaverAware 接口的 Bean 名称(这些 Bean 会感知类加载器的变化)
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    String[] var3 = weaverAwareNames;
    int var4 = weaverAwareNames.length;

    // 遍历这些实现了 LoadTimeWeaverAware 接口的 Bean,触发它们的初始化
    for (int var5 = 0; var5 < var4; ++var5) {
        String weaverAwareName = var3[var5];
        this.getBean(weaverAwareName);  // 获取并初始化这些 Bean
    }

    // 设置 BeanFactory 的临时类加载器为 null,通常在完成 BeanFactory 初始化后释放不再需要的类加载器
    beanFactory.setTempClassLoader((ClassLoader)null);

    // 冻结 BeanFactory 配置,意味着后续无法再修改其配置
    beanFactory.freezeConfiguration();

    // 预先实例化所有单例 Bean,确保所有 Bean 都已初始化
    beanFactory.preInstantiateSingletons();
}

在进行实例化之前,会冻结beanFactory的所有配置:

public void freezeConfiguration() {
    // 将 configurationFrozen 设置为 true,表示 BeanFactory 的配置已经被冻结,不允许进一步修改
    this.configurationFrozen = true;

    // 将 beanDefinitionNames(Bean 定义名称的集合)转换为字符串数组,并保存到 frozenBeanDefinitionNames 中
    // 这使得 Bean 定义名称不可再修改,因为 frozenBeanDefinitionNames 是被冻结的副本
    this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

然后进行实例化所有单例Bean

public void preInstantiateSingletons() throws BeansException {
    // 如果日志级别是 TRACE,则输出调试信息,表示正在进行单例 Bean 的预实例化
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Pre-instantiating singletons in " + this);
    }

    // 获取所有的 Bean 定义名称,并将其存储在一个新的列表中
    List<String> beanNames = new ArrayList(this.beanDefinitionNames);
    Iterator var2 = beanNames.iterator();

    // 第一个循环:实例化所有符合条件的单例 Bean
    String beanName;
    while(var2.hasNext()) {
        beanName = (String)var2.next();
        // 获取该 Bean 的合并后的 Bean 定义(包含父类的定义)
        RootBeanDefinition bd = this.getMergedLocalBeanDefinition(beanName);
        
        // 检查 Bean 是否是抽象的、是否是单例、是否需要懒加载
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 如果是工厂 Bean,先从工厂获取 Bean 实例
            if (this.isFactoryBean(beanName)) {
                Object bean = this.getBean("&" + beanName);
                // 如果是 SmartFactoryBean,并且标记为急切初始化,则提前初始化该 Bean
                if (bean instanceof SmartFactoryBean) {
                    SmartFactoryBean<?> smartFactoryBean = (SmartFactoryBean)bean;
                    if (smartFactoryBean.isEagerInit()) {
                        this.getBean(beanName);
                    }
                }
            } else {
                // 直接获取普通的单例 Bean
                this.getBean(beanName);
            }
        }
    }

    // 第二个循环:处理所有实现了 SmartInitializingSingleton 的单例 Bean
    var2 = beanNames.iterator();
    while(var2.hasNext()) {
        beanName = (String)var2.next();
        // 获取 Bean 的实例
        Object singletonInstance = this.getSingleton(beanName);
        
        // 如果该 Bean 实现了 SmartInitializingSingleton 接口,则调用 afterSingletonsInstantiated()
        if (singletonInstance instanceof SmartInitializingSingleton) {
            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
            // 记录启动步骤,表示智能初始化的过程
            StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
            // 调用 afterSingletonsInstantiated() 方法
            smartSingleton.afterSingletonsInstantiated();
            // 结束启动步骤
            smartInitialize.end();
        }
    }
}
  • 首先创建一个beanDefinitionNames的样本:
    List<String> beanNames = new ArrayList(this.beanDefinitionNames);
    - 这种对全局变量创建副本的方式能够避免线程安全的问题,因为方法里的局部变量不存在线程安全问题
  • 在对beanNames进行遍历时
    • 合并Bean的定义
    • 判断是否是非抽象的、单例且不是懒加载的
      • 是否是工厂
        • 是工厂,通过前缀&获取工厂实例
          • 判断是否需要紧急初始化
        • 不是工厂则通过实例化获取bean
  • 处理所有实现了 SmartInitializingSingleton 的单例 Bean
    • 会在所有单例bean实例化后,统一调用实现了SmartInitializingSingleton接口的的beanafterSingletonsInstantiated()方法

SmartInitializingSingleton 是 Spring 框架中的一个接口,主要用于在 Spring 容器初始化过程中,在所有单例 Bean 实例化后执行额外的操作。它提供了一个回调方法 afterSingletonsInstantiated(),该方法会在所有单例 Bean 完成实例化后被调用。
这个算一个扩展点:在所有bean都实例化后我们该干些什么

12、完成刷新

protected void finishRefresh() {
    // 清理资源缓存,释放不再需要的资源
    this.clearResourceCaches();
    
    // 初始化生命周期处理器,处理与生命周期相关的操作
    this.initLifecycleProcessor();
    
    // 通过生命周期处理器执行“刷新”操作,通常会调用某些 bean 的生命周期方法
    this.getLifecycleProcessor().onRefresh();
    
    // 发布一个 `ContextRefreshedEvent` 事件,表示上下文已经刷新完成
    this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
    
    // 如果应用不是在原生镜像中运行,注册当前应用上下文,以便在 Beans View 中显示
    if (!NativeDetector.inNativeImage()) {
        LiveBeansView.registerApplicationContext(this);
    }
}
  • 在初始化工作全部结束后,spring会发布一个ContextRefreshedEvent 事件,表示上下文已经刷新完成
    因此我们可以写一个listener来监听这个事件,并在刷新结束后执行一些操作:
@Component
public class MyListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 当容器启动完成并发布 ContextRefreshedEvent 事件时执行
        System.out.println("容器已经启动,我们可以做些初始化的操作");
    }
}

查看核心代码getBean()

public Object getBean(String name) throws BeansException {  
    return this.doGetBean(name, (Class)null, (Object[])null, false);  
}

继续向下看doGetBean(),Spring框架中do开头的方法为具体的做事方法

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    // 转换 Bean 名称,name统一转化为beanName,因为name可能是别名
    String beanName = this.transformedBeanName(name);
    
    // 尝试从单例缓存中获取实例
    Object sharedInstance = this.getSingleton(beanName);
    Object beanInstance;

    // 如果单例实例存在并且没有传递构造参数
    if (sharedInstance != null && args == null) {
        // 检查并记录日志
        if (this.logger.isTraceEnabled()) {
            if (this.isSingletonCurrentlyInCreation(beanName)) {
                this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
            } else {
                this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 获取 Bean 实例,可能是 FactoryBean 的对象
        beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        
    } else {
    
        // 检查原型模式下是否存在循环依赖,若存在则抛出异常
        if (this.isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 递归从父工厂中获取 Bean(如果存在父工厂且当前工厂中未定义此 Bean)
        //有点像双亲委派
        BeanFactory parentBeanFactory = this.getParentBeanFactory();
        if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {

			// 根据name获取beanName,如果name以&开头,就会返回&+beanName
            String nameToLookup = this.originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                AbstractBeanFactory abf = (AbstractBeanFactory)parentBeanFactory;
                return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }

            // 根据类型或构造参数获取 Bean
            if (args != null) {
                return parentBeanFactory.getBean(nameToLookup, args);
            }
            if (requiredType != null) {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            return parentBeanFactory.getBean(nameToLookup);
        }

        // 如果不是仅检查类型,将此 Bean 标记为已创建
        if (!typeCheckOnly) {
            this.markBeanAsCreated(beanName);
        }

        // 记录 Bean 实例化的性能指标
        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);

        try {
            // 根据需要的类型记录性能监控信息
            if (requiredType != null) {
                Objects.requireNonNull(requiredType);
                beanCreation.tag("beanType", requiredType::toString);
            }

            // 合并 Bean 定义信息
            RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
            // 检查合并的 Bean 定义是否满足条件
            this.checkMergedBeanDefinition(mbd, beanName, args);

            // 判断当前创建的 Bean 是否有依赖项
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // 检查是否存在循环依赖
                    if (this.isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    //不存在depends-on循环依赖就会进行注册
                    this.registerDependentBean(dep, beanName);

                    // 确保依赖项被实例化
                    try {
	                    //递归实例化
                        this.getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 根据不同作用域实例化 Bean
            if (mbd.isSingleton()) {
                // 创建单例 Bean 并缓存
				// 通过getSingleton(beanName,singletonFactory)方法获取实例对象
				// 使用lambda表达式来实现匿名内部类,传入singletonFactory参数
                sharedInstance = this.getSingleton(beanName, () -> {
                    try {
						// 核心方法,这里完成创建Bean对象(重点)
                        return this.createBean(beanName, mbd, args);
                    } catch (BeansException ex) {
						// 如果创建过程中发生异常,则会进行销毁
                        this.destroySingleton(beanName);
                        throw ex;
                    }
                });
                //判断是否是BeanFactory还是普通的bean
                beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            //实例化多例bean
            //和单例bean的区别是不会存储到缓存中
            } else if (mbd.isPrototype()) {
                // 创建原型 Bean
                Object prototypeInstance;
                try {
                    this.beforePrototypeCreation(beanName);
                    prototypeInstance = this.createBean(beanName, mbd, args);
                } finally {
                    this.afterPrototypeCreation(beanName);
                }
                beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } else {
                // 实例化其他作用域的bean
                String scopeName = mbd.getScope();
                if (!StringUtils.hasLength(scopeName)) {
                    throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
                }
                Scope scope = (Scope)this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }

                try {
                    // 从自定义作用域中获取 Bean
                    Object scopedInstance = scope.get(beanName, () -> {
                        this.beforePrototypeCreation(beanName);
                        try {
                            return this.createBean(beanName, mbd, args);
                        } finally {
                            this.afterPrototypeCreation(beanName);
                        }
                    });
                    beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                } catch (IllegalStateException ex) {
                    throw new ScopeNotActiveException(beanName, scopeName, ex);
                }
            }
        } catch (BeansException ex) {
            // 捕获 Bean 创建过程中的异常并记录
            beanCreation.tag("exception", ex.getClass().toString());
            beanCreation.tag("message", String.valueOf(ex.getMessage()));
            this.cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        } finally {
            // 结束性能监控
            beanCreation.end();
        }
    }

    // 将实例适配到所需类型
    return this.adaptBeanInstance(name, beanInstance, requiredType);
}

大致流程:

  • 转换别名,获取能够解析的beanName
  • 尝试从缓存中获取,获取到则返回该bean
  • 若缓存没有,则判断是否存在父工厂且本地工厂不存在该bean
    • 满足则将由父工厂创建该bean
  • 父工厂不存在则,由自己进行创建
    • 先获取该bean的依赖项,然后循环通过getBean()递归优先实例化
    • 合并bean的定义,判断作用范围
      • 是单例的,调用getSingleton()过程中会进行缓存
      • 是多例的,在createBean()过程中不会进行缓存
      • 其他的自定义范围也会走createBean()

接下来看单例bean的构建过程:

if (mbd.isSingleton()) {
	// 创建单例 Bean 并缓存
	// 通过 getSingleton(beanName, singletonFactory) 方法获取实例对象
	// 使用 lambda 表达式来实现匿名内部类,传入 singletonFactory 参数
	sharedInstance = this.getSingleton(beanName, () -> {
		try {
			// 核心方法,这里完成创建 Bean 对象(重点)
			return this.createBean(beanName, mbd, args);
		} catch (BeansException ex) {
			// 如果创建过程中发生异常,则会销毁该单例实例
			this.destroySingleton(beanName);
			throw ex;
		}
	});
	// 判断是否是 FactoryBean,如果是则调用 getObjectForBeanInstance 获取实际对象;
	// 否则直接返回单例 bean 实例
	beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

查看getSingleton源码:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // 确保 beanName 不为空
    Assert.notNull(beanName, "Bean name must not be null");

    // 加锁保证线程安全
    synchronized(this.singletonObjects) {
        // 从缓存中获取已创建的单例对象
        Object singletonObject = this.singletonObjects.get(beanName);
        
        // 如果缓存中没有该单例对象,则创建新实例
        if (singletonObject == null) {
            // 如果当前正在销毁单例对象,抛出异常禁止创建新单例
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }

            // 输出调试日志信息
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }

            // 在单例对象创建之前执行前置操作
            this.beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = this.suppressedExceptions == null;
            
            // 记录异常信息
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }

            try {
                // 使用 singletonFactory 创建单例对象
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            } catch (IllegalStateException ex) {
                // 如果出现异常,再次尝试从缓存获取单例对象
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            } catch (BeanCreationException ex) {
                // 在抛出异常之前,添加 suppressedExceptions 信息
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            } finally {
                // 清除 suppressedExceptions 记录
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                // 在单例对象创建之后执行后置操作
                this.afterSingletonCreation(beanName);
            }

            // 如果成功创建新单例,将其加入缓存
            if (newSingleton) {
                this.addSingleton(beanName, singletonObject);
            }
        }

        return singletonObject; // 返回单例对象
    }
}

这个方法首先会获取this.singletonObjects.get(beanName)获取一个bean

而这个singletonObjects其实就是一个Map
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);

具体的实例化过程在singletonObject = singletonFactory.getObject();这句话

在传参的时候,通过匿名内部类重写了,getObject()方法,通过调用createBean(beanName, mbd, args);来进行实例化

上面是单例bean的实例化过程,可以看到最后会将单例对象做一个缓存。

下面看一下多例bean的实例化:

else if (mbd.isPrototype()) {  
    var12 = null;  
  
    Object prototypeInstance;  
    try {  
        this.beforePrototypeCreation(beanName);  
        prototypeInstance = this.createBean(beanName, mbd, args);  
    } finally {  
        this.afterPrototypeCreation(beanName);  
    }  
  
    beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
}

并没有调用getSingleton,而是直接调用createBean(beanName, mbd, args);,因此并没有缓存。

如何创建的对象呢?查看createBean()

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    // 如果日志级别是 TRACE,则记录创建 Bean 的开始过程
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Creating instance of bean '" + beanName + "'");
    }

    // 克隆 BeanDefinition,如果需要,将解析后的类替换到克隆的定义中
    RootBeanDefinition mbdToUse = mbd;
    Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        // 创建一个新的 RootBeanDefinition,用于承载解析后的类
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    try {
        // 准备方法重写配置(如果有),用于支持动态代理、CGLIB等功能
        mbdToUse.prepareMethodOverrides();
    } catch (BeanDefinitionValidationException var9) {
        // 如果方法重写配置校验失败,抛出异常
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
    }

    Object beanInstance;

    try {
        // 尝试通过 BeanPostProcessor 在实例化前返回一个实例
        beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
        if (beanInstance != null) {
            // 如果提前生成了 Bean 实例,直接返回
            return beanInstance;
        }
    } catch (Throwable var10) {
        // 捕获实例化前的处理异常,包装成 BeanCreationException
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
    }

    try {
        // 执行实际的 Bean 创建过程
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);

        // 如果日志级别是 TRACE,记录创建完成的信息
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Finished creating instance of bean '" + beanName + "'");
        }

        // 返回创建完成的 Bean 实例
        return beanInstance;
    } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
        // 对隐式出现的单例异常和已有的创建异常直接抛出
        throw var7;
    } catch (Throwable var8) {
        // 捕获其他异常,包装为 BeanCreationException 并抛出
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
    }
}

这段可以作为一个参考:
在使用某个遍历,可以做一个拷贝,然后操作这个局部变量。
局部变量天生局部线程安全的特性

// 克隆 BeanDefinition,如果需要,将解析后的类替换到克隆的定义中
    RootBeanDefinition mbdToUse = mbd;
    Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        // 创建一个新的 RootBeanDefinition,用于承载解析后的类
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

实例化的核心代码:

beanInstance = this.doCreateBean(beanName, mbdToUse, args);

doCreateBean源码:

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    // 定义一个 BeanWrapper 用于封装 Bean 实例
    BeanWrapper instanceWrapper = null;

    // 如果是单例 Bean,则尝试从缓存中获取实例包装对象
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
    }

    // 如果缓存中没有实例包装对象,则通过创建新的 Bean 实例
    if (instanceWrapper == null) {
        instanceWrapper = this.createBeanInstance(beanName, mbd, args);
    }

    // 获取实例对象和类信息
    Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        // 设置目标类型到 Bean 定义中
        mbd.resolvedTargetType = beanType;
    }

    // 允许修改合并后的BeanDefinition,提供的扩展点
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            } catch (Throwable var17) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
            }

            // 标记为已处理
            mbd.markAsPostProcessed();
        }
    }

    // 检查是否需要提前暴露单例(用于处理循环依赖)
    boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
    if (earlySingletonExposure) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
        }

        // 提前暴露单例,通过 ObjectFactory 提供早期引用
        this.addSingletonFactory(beanName, () -> this.getEarlyBeanReference(beanName, mbd, bean));
    }

    // 初始化暴露的对象
    Object exposedObject = bean;

    try {
        // 填充 Bean 的属性(依赖注入)
        this.populateBean(beanName, mbd, instanceWrapper);

        // 初始化 Bean,包括调用初始化方法和 BeanPostProcessor 的方法
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable var18) {
        // 处理异常,并将其包装为 BeanCreationException
        if (var18 instanceof BeanCreationException) {
            BeanCreationException bce = (BeanCreationException) var18;
            if (beanName.equals(bce.getBeanName())) {
                throw bce;
            }
        }

        throw new BeanCreationException(mbd.getResourceDescription(), beanName, var18.getMessage(), var18);
    }

    // 再次检查早期暴露的单例,处理循环依赖问题
    if (earlySingletonExposure) {
        Object earlySingletonReference = this.getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            // 如果暴露的对象与当前 Bean 不一致,可能是因为包装问题,进行处理
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                String[] dependentBeans = this.getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }

                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    try {
        // 注册销毁方法(如果必要)
        this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
        // 返回最终暴露的对象
        return exposedObject;
    } catch (BeanDefinitionValidationException var16) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
    }
}

BeanWrapper 是 Spring Framework 中的一个接口,定义在 org.springframework.beans 包下。它是 Spring 的 Bean 操作工具之一,用于封装一个具体的 Java Bean,并提供对该 Bean 的属性进行操作的功能,包括属性的获取、设置和类型转换。

doCreateBean()方法大致分为如下步骤:

  1. 实例化阶段:使用 BeanWrapper 对象进行包装,判断缓存是否存在,如果不存在,则实例化 bean 对象。
  2. BeanDefinition后置处理:提供扩展点,允许在合并后的 BeanDefinition上进行修改。
  3. 循环依赖处理:如果Bean是单例、支持循环引用,并且正在创建中,将对象放入singletonFactories三级缓存。
  4. 依赖注入阶段:进行Bean的属性填充。
  5. 初始化阶段:初始化Bean对象。
  6. 处理循环依赖的提前暴露:如果之前进行了循环依赖的提前暴露,获取提前暴露的Bean引用,根据条件更新Bean
  7. 注册需要销毁的Bean:根据需要,注册需要销毁的Bean

查看createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 获取 Bean 的类对象
    Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
    if (beanClass != null 
        && !Modifier.isPublic(beanClass.getModifiers()) // 检查类是否是 public
        && !mbd.isNonPublicAccessAllowed()) { // 是否允许非 public 访问
        throw new BeanCreationException(
            mbd.getResourceDescription(), 
            beanName, 
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()
        );
    } else {
        // 如果定义了自定义的实例供应商(Supplier),优先使用它来创建实例
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return this.obtainFromSupplier(instanceSupplier, beanName);
        } 
        
        // 如果配置了工厂方法,使用工厂方法实例化 Bean
        else if (mbd.getFactoryMethodName() != null) {
            return this.instantiateUsingFactoryMethod(beanName, mbd, args);
        } else {
            // 定义两个标志位
            boolean resolved = false; // 是否已经解析过构造函数
            boolean autowireNecessary = false; // 是否需要自动注入

            // 如果没有传递构造函数参数,尝试从缓存中获取构造函数解析结果
            if (args == null) {
                synchronized(mbd.constructorArgumentLock) {
                    if (mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }

            // 如果已经解析过构造函数,根据是否需要自动注入决定实例化策略
            if (resolved) {
                return autowireNecessary 
                    ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) 
                    : this.instantiateBean(beanName, mbd);
            } else {
                // 从 BeanPostProcessor 中确定可能的构造函数
                Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                
                // 如果没有明确的构造函数需要解析且没有构造函数参数,则使用默认构造函数
                if (ctors == null 
                    && mbd.getResolvedAutowireMode() != 3 // 非构造函数注入模式
                    && !mbd.hasConstructorArgumentValues() // 没有显式的构造参数
                    && ObjectUtils.isEmpty(args)) { // 参数为空
                    ctors = mbd.getPreferredConstructors();
                    return ctors != null 
                        ? this.autowireConstructor(beanName, mbd, ctors, (Object[])null) 
                        : this.instantiateBean(beanName, mbd);
                } else {
                    // 使用自动注入策略的构造函数
                    return this.autowireConstructor(beanName, mbd, ctors, args);
                }
            }
        }
    }
}

createBeanInstance()方法大致做了如下工作:

  1. 获取并判断Bean类型:从BeanDefinition中获取Bean的类。判断如果Bean类不是公共类且不允许访问非公共类,则抛出异常。
  2. 实例化Bean:如果存在instanceSupplier,存在则直接获取实例。否则,根据工厂方法或构造方法实例化Bean。
  3. 判断是否已确定构造方法:如果已经确定构造方法,根据情况选择有参或无参构造方法。
  4. 推断构造方法:如果不确定构造方法,则获取Bean对应的所有构造方法,如果找到了进行创建Bean ,没有找到则会直接使用无参的构造方法完成Bean的初始化。

由此可知,createBeanInstance方法负责解析Bean类、选择构造函数、执行自动装配,最终创建Bean实例并返回

然后接着看填充bean和初始化bean

// 填充 Bean 的属性(依赖注入)
this.populateBean(beanName, mbd, instanceWrapper);

// 初始化 Bean,包括调用初始化方法和 BeanPostProcessor 的方法
exposedObject = this.initializeBean(beanName, exposedObject, mbd);

先看populateBean()

populateBean 方法是 Spring 框架的核心方法之一,用于为 Bean 设置属性值并执行相关的依赖注入逻辑。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 如果 BeanWrapper 为 null,并且有属性值,则抛出异常
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Cannot apply property values to null instance");
        }
        // 如果没有属性值且 BeanWrapper 为空,直接返回
        return;
    }

    // 如果 Bean 不是合成的(非框架内部生成),并且存在 InstantiationAwareBeanPostProcessor
    if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
        // 遍历所有 InstantiationAwareBeanPostProcessor
        Iterator<InstantiationAwareBeanPostProcessor> var4 =
            this.getBeanPostProcessorCache().instantiationAware.iterator();
        while (var4.hasNext()) {
            InstantiationAwareBeanPostProcessor bp = var4.next();
            // 如果任何一个 postProcessAfterInstantiation 方法返回 false,停止属性注入
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }

    // 获取定义中的属性值
    PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;

    // 获取自动装配模式,1 = AUTOWIRE_BY_NAME, 2 = AUTOWIRE_BY_TYPE
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
        // 创建新的属性集合,复制原始属性值
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // 根据自动装配模式,执行按名称或按类型的依赖注入
        if (resolvedAutowireMode == 1) {
            this.autowireByName(beanName, mbd, bw, newPvs); // 按名称注入
        }
        if (resolvedAutowireMode == 2) {
            this.autowireByType(beanName, mbd, bw, newPvs); // 按类型注入
        }

        // 更新属性值为新生成的集合
        pvs = newPvs;
    }

    // 再次调用 InstantiationAwareBeanPostProcessor 处理属性
    if (this.hasInstantiationAwareBeanPostProcessors()) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        // 遍历所有的 InstantiationAwareBeanPostProcessor
        PropertyValues pvsToUse;
        Iterator<InstantiationAwareBeanPostProcessor> var11 =
            this.getBeanPostProcessorCache().instantiationAware.iterator();
        while (var11.hasNext()) {
            InstantiationAwareBeanPostProcessor bp = var11.next();
            // 调用 postProcessProperties 方法,允许修改属性值
            pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                // 如果处理器返回 null,停止属性注入
                return;
            }
            pvs = pvsToUse; // 更新属性值
        }
    }

    // 检查依赖项(比如是否有未满足的强制依赖)
    boolean needsDepCheck = mbd.getDependencyCheck() != 0;
    if (needsDepCheck) {
        // 筛选需要检查依赖的属性描述符
        PropertyDescriptor[] filteredPds =
            this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        // 执行依赖检查
        this.checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    // 将最终的属性值应用到 Bean 上
    if (pvs != null) {
        this.applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

流程:

  1. 检查是否可以为 Bean 设置属性值
    • 如果 BeanWrappernullRootBeanDefinition 中存在属性值,则抛出异常。
    • BeanWrapper 是一个工具类,用于封装 Bean 实例并提供对其属性的访问。
  2. 执行 InstantiationAwareBeanPostProcessor 的后处理器逻辑
    • 调用所有实现了 InstantiationAwareBeanPostProcessor 的 BeanPostProcessor,依次执行其 postProcessAfterInstantiation 方法。如果其中一个返回 false,则直接退出,不设置属性值。
  3. 根据自动装配模式进行注入
    resolvedAutowireMode 解析依赖注入的方式,将属性装配到 PropertyValues
    • 如果自动装配模式为 byNamebyType
      • byName
        根据属性名在 Spring 容器中查找对应的 Bean,并将其注入到目标属性中。
      • byType
        根据属性的类型在 Spring 容器中查找匹配的 Bean。如果有多个符合的候选项,会报错。
  4. 再次调用 InstantiationAwareBeanPostProcessor 的逻辑
    • 调用所有实现了 InstantiationAwareBeanPostProcessorpostProcessProperties 方法,允许进一步修改或替换属性值。
    • 如果任何一个处理器返回 null,则直接退出。
  5. 执行依赖检查
    • 检查是否存在未满足的依赖,如果有未注入的属性(比如 @Required 注解标注的属性未赋值),则抛出异常。
  6. 应用属性值
    • 使用 applyPropertyValues 方法设置注入好的属性值给BeanWrapper,最终完成属性的填充。

扩展
InstantiationAwareBeanPostProcessor 是一个重要的扩展点,允许开发者在 Bean 实例化后对其属性进行额外的处理。

  • postProcessAfterInstantiation
    • 如果返回 false,表示不再继续属性注入。
  • postProcessProperties
    • 可以修改 Bean 的属性值,返回新的 PropertyValues

接下来看初始化函数initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    // 调用 Aware 接口方法,例如 BeanNameAware、BeanFactoryAware 等,
    // 用于注入 Spring 容器或上下文信息到 Bean 中
    this.invokeAwareMethods(beanName, bean);

    // wrappedBean 是当前处理的 Bean 实例,初始化时可能会被替换为代理对象
    Object wrappedBean = bean;

    // 如果当前 Bean 不是 synthetic(非 Spring 内部 Bean),
    // 则调用所有 BeanPostProcessor 的 postProcessBeforeInitialization 方法
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    }

    try {
        // 调用 Bean 的初始化方法,包括:
        // 1. 如果实现了 InitializingBean,则调用其 afterPropertiesSet 方法;
        // 2. 如果在配置中指定了 init-method,则调用指定方法
        this.invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable ex) {
        // 如果初始化方法抛出异常,包装为 BeanCreationException 抛出
        throw new BeanCreationException(
            mbd != null ? mbd.getResourceDescription() : null,
            beanName,
            ex.getMessage(),
            ex
        );
    }

    // 如果当前 Bean 不是 synthetic(非 Spring 内部 Bean),
    // 则调用所有 BeanPostProcessor 的 postProcessAfterInitialization 方法
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    // 返回最终处理后的 Bean 实例(可能是原始对象或代理对象)
    return wrappedBean;
}

initializeBean()方法大致做了如下工作:

  1. Aware接口回调:回调实现了AwareMethods接口的Bean。调用顺序依次为实现BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的Bean
  2. 调用初始化前的前置处理器:调用BeanPostProcessor初始化前的方法,在初始化之前对Bean进行增强处理。
  3. 调用初始化方法:进行调用Bean的初始化方法。
  4. 调用初始化后的后置处理器:最后,调用BeanPostProcessor初始化后的方法,在初始化之后对Bean进行处理,触发Bean的后置处理,AOP代理对象也在该阶段产生(这里说法有些不严谨,在后续讲循环依赖时,会分析哪种情况下提前生成AOP代理对象)。

由此可知,initializeBean()方法主要负责在Spring容器中初始化Bean,包括回调Aware接口、前置处理、初始化方法调用和后置处理等

查看初始化前的前置处理方法,其他的类似就不重复看了:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    // 初始化结果变量,用于存储经过处理器修改后的 Bean 实例
    Object result = existingBean;

    // 遍历所有注册的 BeanPostProcessor
    for (Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
        // 获取当前的 BeanPostProcessor 实例
        BeanPostProcessor processor = (BeanPostProcessor) var4.next();

        // 调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法
        // 此方法会对当前 Bean 进行“初始化前”的处理
        Object current = processor.postProcessBeforeInitialization(result, beanName);

        // 如果某个处理器返回 null,直接终止后续处理并返回当前结果
        if (current == null) {
            return result; // 保留当前的 result,并终止循环
        }

        // 更新 result 为最新处理的 Bean 实例
        result = current;
    }

    // 返回最终处理后的 Bean 实例
    return result;
}

![[77dd5cbd97fd12160bdf44d954a1c5d6.png]]

第五章 循环引用

1、产生的问题

在写代码的时候,发现如下场景:

@Component
public class A {
    private B b;

    @Autowired
    public A(B b) {
        this.b = b;
    }
}

@Component
public class B {
    private A a;

    @Autowired
    public B(A a) {
        this.a = a;
    }
}

启动工程会报以下的错误,A构造需要B,B构造需要A,循环依赖

在这里插入图片描述

在代码中:

  • AB 通过构造函数互相依赖。
    • A 的构造函数需要 B
    • B 的构造函数需要 A

这种循环依赖会导致 Spring 在创建 Bean 的过程中无法完成依赖注入,因为:

  1. Spring 在实例化 A 时需要 B,而 B 需要先被创建。
  2. 在尝试创建 B 时,又需要先创建 A
  3. 这个过程会无限循环,最终抛出 BeanCurrentlyInCreationException

Spring中,通常Bean对象设置属性有三种方式:

  • 基于构造方法注入:
    • 方式一:
    @Component
    public class A {
        private B b;
    
        @Autowired
        public A(B b) {
            this.b = b;
        }
    }
    
    @Component
    public class B {
        private A a;
    
        @Autowired
        public B(A a) {
            this.a = a;
        }
    }
    
    
    • 方式二:
    public class A {
    
    	private B b;
    
    	public A(B b) {
    		this.b = b;
    	}
    }
    
    
    xml配置文件:
    <bean id="bBean" class="com.Guo.B"/>
    
    <bean id="aBean" class="com.Guo.A">
    	<constructor-arg ref="bBean"/>
    </bean>
    
  • 基于set方法注入
    @Component
    public class A {
        private B b;
    
        @Autowired
        public void setB(B b) {
            this.b = b;
        }
    }
    
    @Component
    public class B {
        private A a;
    
        @Autowired
        public void setA(A a) {
            this.a = a;
        }
    }
    
  • 基于属性注入
    @Component
    public class A {
    	@Autowired
    	private B b;
    	
    }
    

上面三种属性注入情况,若产生循环依赖,实际上Spring只能解决后两者,而基于构造方法注入产生的循环依赖,Spring是处理不了的。

这里为什么处理不了基于构造方法注入产生的循环依赖呢?

  • 其实Spring解决循环依赖的本质是将实例化和初始化分离,在实例化之后产生缓存,允许其它对象引用。
  • 而构造方法注入,在解析构造方法参数时就会去创建引用对象,而当前类自身还没有完成实例化,如果引用对象又依赖当前对象,则会产生死循环,均无法创建。

2、基础解决方案

在之前讲解getBean()代码的时候,在doCreateBean()里提到一个早期暴露bean的一个概念,代码如下:

// 检查是否需要提前暴露单例以解决循环依赖
boolean earlySingletonExposure = mbd.isSingleton() // 当前 bean 是否是单例模式
    && this.allowCircularReferences // 是否允许循环依赖
    && this.isSingletonCurrentlyInCreation(beanName); // 当前 bean 是否正在创建中

if (earlySingletonExposure) {
    // 如果开启日志跟踪,输出调试信息
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
    }

    // 提前将当前 bean 的工厂对象加入单例缓存
    this.addSingletonFactory(beanName, () -> {
        // 获取对当前 bean 的早期引用(如代理对象)
        return this.getEarlyBeanReference(beanName, mbd, bean);
    });
}

会判断bean是否是单例、正在创建中且上下文支持循环引用,

  • 满足则会将创建了的、未初始化和属性填充的==半创建bean==加入到缓存中

提前暴露的意义

  • 解决“构造器循环依赖”或“属性循环依赖”的问题。
  • 避免在创建过程中的依赖失败。

具体的是addSingletonFactory()方法:

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    // 检查传入的 singletonFactory 是否为空,防止非法参数
    Assert.notNull(singletonFactory, "Singleton factory must not be null");

    // 对 singletonObjects 进行同步,确保线程安全
    synchronized (this.singletonObjects) {
        // 如果当前单例对象缓存中尚未包含该 bean 的实例
        if (!this.singletonObjects.containsKey(beanName)) {
            // 将传入的单例工厂对象存入 singletonFactories 中
            this.singletonFactories.put(beanName, singletonFactory);

            // 如果 earlySingletonObjects 中有该 bean,移除它
            // 因为我们希望通过工厂方法动态生成早期引用,而不是使用缓存的实例
            this.earlySingletonObjects.remove(beanName);

            // 将 bean 名称记录到 registeredSingletons 中,表示已经注册过
            this.registeredSingletons.add(beanName);
        }
    }
}

上面的代码涉及到三级缓存:

/** 一级缓存,存储所有创建好的完整单例Bean */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 三级缓存,存储创建Bean的工厂对象 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** 二级缓存,存储未创建好的半成品单例Bean */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
  • 一级缓存(singletonObjects):
    存储所有已经创建好的完整单例Bean,即我们常说的单例池缓存
  • 二级缓存(earlySingletonObjects):
    存储未创建好的半成品单例Bean,即我们常说的提前暴露缓存
  • 三级缓存(singletonFactories):
    存储创建Bean的工厂对象,即我们常说的工厂对象缓存

查看传入的bean工厂getEarlyBeanReference()方法:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    // 初始暴露的对象,默认是当前传入的 bean 实例
    Object exposedObject = bean;

    SmartInstantiationAwareBeanPostProcessor bp;
    // 如果 Bean 不是 synthetic(即不是 Spring 内部使用的特殊 Bean),
    // 且存在 InstantiationAwareBeanPostProcessor 类型的后置处理器
    if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {

        // 遍历缓存中的 SmartInstantiationAwareBeanPostProcessor 实例
        for (Iterator var5 = this.getBeanPostProcessorCache().smartInstantiationAware.iterator();
             var5.hasNext(); 
             exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)) {
            // 获取一个 SmartInstantiationAwareBeanPostProcessor 实例
            bp = (SmartInstantiationAwareBeanPostProcessor) var5.next();

            // 调用 getEarlyBeanReference 方法,允许后置处理器对暴露的 Bean 进行自定义处理
            // 处理后的 Bean 替换 exposedObject
        }
    }

    // 返回经过所有后置处理器处理后的暴露对象
    return exposedObject;
}

SmartInstantiationAwareBeanPostProcessor 的作用
SmartInstantiationAwareBeanPostProcessorBeanPostProcessor 的一种扩展,其主要功能是对 Bean 的早期引用进行额外的处理。
在循环依赖场景下,这个处理过程非常重要,比如:
- 创建代理对象(如使用 AOP 时,返回的是代理对象而不是原始对象)。
- 提前修改 Bean 的某些属性。

getEarlyBeanReference 方法
getEarlyBeanReferenceSmartInstantiationAwareBeanPostProcessor 的一个方法,允许自定义 Bean 的早期引用:

public Object getEarlyBeanReference(Object bean, String beanName) {
    // 生成缓存键,用于标识当前 Bean 的代理对象
    Object cacheKey = this.getCacheKey(bean.getClass(), beanName);

    // 将当前 Bean 暂存到 earlyProxyReferences 中,表明这个 Bean 将被代理或已被处理
    this.earlyProxyReferences.put(cacheKey, bean);

    // 检查是否需要代理当前 Bean,如果需要,则包装成代理对象返回
    return this.wrapIfNecessary(bean, beanName, cacheKey);
}

它可以返回原始的 Bean,或者是一个经过加工后的(例如,AOP 代理)的对象。

还记得在doGetBean()时,会先从缓存中获取:

Object sharedInstance = this.getSingleton(beanName);

查看getSingleton()源码:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从单例对象缓存中获取单例对象
    Object singletonObject = this.singletonObjects.get(beanName);
    
    // 如果单例对象尚未创建且当前单例正在创建中
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        // 尝试从早期单例对象缓存中获取
        singletonObject = this.earlySingletonObjects.get(beanName);

        // 如果早期对象缓存也不存在且允许早期引用
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                // 再次检查单例缓存,确保线程安全
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    // 再次检查早期单例对象缓存
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                        // 获取对应的单例工厂
                        ObjectFactory<?> singletonFactory = (ObjectFactory<?>) this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            // 通过工厂获取单例对象
                            singletonObject = singletonFactory.getObject();

                            // 将早期单例对象放入缓存
                            this.earlySingletonObjects.put(beanName, singletonObject);

                            // 移除单例工厂,避免重复创建
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }

    return singletonObject;
}

最后,在创建好对象后,就不需要提前暴露,则需要将bean从二级缓存删除,并放入一级缓存,下次获取直接从一级缓存获取即可。该处理逻辑位于getSingleton()的末尾:

if (newSingleton) {  
    this.addSingleton(beanName, singletonObject);  
}

查看addSingleton()源码:

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) { // 对单例对象缓存操作加锁,确保线程安全
        // 将完全初始化的单例对象添加到缓存
        this.singletonObjects.put(beanName, singletonObject);

        // 清理单例工厂缓存,防止后续再通过工厂创建对象
        this.singletonFactories.remove(beanName);

        // 清理早期单例对象缓存,标志该对象已完成初始化
        this.earlySingletonObjects.remove(beanName);

        // 记录该单例对象的名称,便于后续查找或管理
        this.registeredSingletons.add(beanName);
    }
}

3、有代理的循环依赖

上面我们分析到,似乎我们只需要在单例池缓存基础上额外加一层提前暴露缓存即可。

但是这里我们忘了一点,对象A在初始化阶段可能会产生AOP代理对象,最终放入单例池缓存的是A的代理对象,而对象A的属性注入阶段却在初始化阶段之前,这会造成放入提前暴露缓存的是对象A的普通对象,然后对象B注入的是对象A的普通对象,并不是对象A的代理对象,显然存在问题。

很明显,造成这样的问题是由于Bean的生命周期,需要依次执行实例化、属性注入、初始化阶段。

在上一小节的暴露代码中:

if (earlySingletonExposure) {
    // 如果开启日志跟踪,输出调试信息
    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
    }

    // 提前将当前 bean 的工厂对象加入单例缓存
    this.addSingletonFactory(beanName, () -> {
        // 获取对当前 bean 的早期引用(如代理对象)
        return this.getEarlyBeanReference(beanName, mbd, bean);
    });
}

如果需要提前暴露,则会将这个暴露的bean工厂加到三级缓存中。

执行流程:

  • 实例化对象A,将A的工厂放入到三级缓存做早期暴露
  • 对象A依赖B,则会在缓存中找B
    • 从一级缓存➡二级缓存➡三级缓存的次序寻找
    • 在找B时,发现缓存中都没有,则会创建B
      - 实例化B,实例化后将B的工厂放入到三级缓存
      - B依赖于A,则将A注入到B的工厂对象中

此时能够决绝循环依赖问题,但此时注入的都是原始的对象,而不是代理对象

在将A注入到B中,对调用工厂的getObject(),其实就是调用getEarlyBeanReference(beanName, mbd, bean)方法
这个方法有什么用呢?
想必通过上面分析的AOP代理场景下循环依赖解决,大家应该能反应过来。

没错,getEarlyBeanReference()方法其实就是判断对象A是否存在AOP,如果对象A存在AOP,即需要提前创建代理对象A,那么对象B注入的就应该是代理后的对象A,而不是普通对象A

我们进入getEarlyBeanReference()方法源码看一下:

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    // 初始暴露的对象,默认是当前传入的 bean 实例
    Object exposedObject = bean;

    SmartInstantiationAwareBeanPostProcessor bp;
    // 如果 Bean 不是 synthetic(即不是 Spring 内部使用的特殊 Bean),
    // 且存在 InstantiationAwareBeanPostProcessor 类型的后置处理器
    if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {

        // 遍历缓存中的 SmartInstantiationAwareBeanPostProcessor 实例
        for (Iterator var5 = this.getBeanPostProcessorCache().smartInstantiationAware.iterator();
             var5.hasNext(); 
             exposedObject = bp.getEarlyBeanReference(exposedObject, beanName)) {
            // 获取一个 SmartInstantiationAwareBeanPostProcessor 实例
            bp = (SmartInstantiationAwareBeanPostProcessor) var5.next();

            // 调用 getEarlyBeanReference 方法,允许后置处理器对暴露的 Bean 进行自定义处理
            // 处理后的 Bean 替换 exposedObject
        }
    }

    // 返回经过所有后置处理器处理后的暴露对象
    return exposedObject;
}

在这段代码中会返回一个AOP代理对象

因此,在实例化之后,会判断是否需要早期暴露,在暴露的过程中会将其放入到三级缓存,在通过工厂获取对象时,会判断是否需要生产代理对象,需要则返回一个代理对象。

第六章 扩展

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值