Spring 核心容器

Spring 核心容器(Core Container)是 Spring 框架的基础组件之一。它负责创建和管理应用程序中的 Bean。Spring 提供了强大的 IoC(控制反转)和 DI(依赖注入)功能,使得应用程序的组件可以解耦合,提高代码的可维护性和测试性。

1.Spring 核心容器概述:

2.1 BeanFactory 和 ApplicationContext

BeanFactory 是 Spring 容器的根接口,提供了最基本的 Bean 创建和管理功能。它负责实例化、配置和管理 bean。

ApplicationContextBeanFactory 的扩展,提供了更多功能,如国际化、事件发布、AOP 等。ApplicationContext 是大多数应用程序使用的容器接口。

2.2 BeanDefinition

BeanDefinition 是一个描述 Bean 的元数据的类。它包含了 Bean 的类型、作用域、构造函数参数、属性等信息。Spring 容器通过解析 BeanDefinition 来创建和配置 Bean。

2.3 主要实现类

  • DefaultListableBeanFactory:是 BeanFactory 的默认实现,负责管理 Bean 的创建和依赖注入。

  • AbstractApplicationContext:是 ApplicationContext 的抽象实现,提供了容器初始化、刷新和关闭等功能。

2.Spring

既然BeanFactory是我们容器最核心的,那我们来看看他是什么样的?

  String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
        //这个方法通过Class类型来获取某个类型的bean的ObjectProvider,用于懒加载或者多次获取bean。
    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

    boolean containsBean(String name);

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);

BeanFactory很简单就一些定义获取bean的和判断bean类型的方法,那我们再看看子类DefaultListableBeanFactory是怎么实现的?先来看看它的类图:

DefaultListableBeanFactory

  1. AbstractAutowireCapableBeanFactory

  2. 这是 DefaultListableBeanFactory 的直接父类,提供了自动注入、bean 创建等关键功能。它实现了 Spring 的依赖注入机制,并负责管理 bean 的生命周期(例如初始化、销毁)。

  3. ConfigurableListableBeanFactory

  4. DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory 接口,这赋予它对 bean 的全部控制能力,包括预加载、依赖解析、bean 定义的访问和管理等。

  5. BeanDefinitionRegistry

  6. 它实现了 BeanDefinitionRegistry 接口,允许通过注册表方式管理和维护 BeanDefinition,这是 Spring 管理 bean 定义的核心接口。

    先来看看其字段

      @Nullable
      private static Class<?> javaxInjectProviderClass;
    //这是一个静态的 Map,用于存储可序列化的 DefaultListableBeanFactory 实例
      private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories;
      @Nullable
      private String serializationId;
    //这是一个布尔值,表示是否允许覆盖已有的 BeanDefinition。默认情况下设置为 true,意味着当新的 BeanDefinition 被注册时,如果名称相同的 bean 定义已经存在,新的定义会覆盖旧的定义。这个配置可以在应用程序需要严格控制 bean 定义时关闭,以防止意外覆盖
      private boolean allowBeanDefinitionOverriding = true;
    //这是一个布尔值,表示是否允许 Spring 容器在创建 bean 之前加载类。默认设置为 true,表示容器在启动时可以预加载一些 bean 类,通常用于提升性能。但是,如果设置为 false,容器会延迟加载类,直到它们第一次被实际需要时再加载。这对于处理某些类加载问题或性能调优有帮助
      private boolean allowEagerClassLoading = true;
      @Nullable
    //用于对 bean 的依赖项进行排序
      private Comparator<Object> dependencyComparator;
    //用于决定某个 bean 是否是自动注入的候选对象
      private AutowireCandidateResolver autowireCandidateResolver;
    //这个 Map 保存了可解析的依赖项,通常是一些基础设施类的对象
      private final Map<Class<?>, Object> resolvableDependencies;
    //用于存储所有已注册的 BeanDefinition。通过 beanName 作为键,它可以快速找到相应的 BeanDefinition。这是容器管理和查找 bean 定义的基础。
      private final Map<String, BeanDefinition> beanDefinitionMap;
    //这个 Map 用于存储合并后的 BeanDefinition,即当一个 bean 继承了其他 BeanDefinition 时,Spring 会将其合并。BeanDefinitionHolder 包含了 BeanDefinition 以及一些额外的元数据信息。这种合并后的 BeanDefinition 是用于实际创建 bean 实例的。
      private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders;
    //这个 Map 按类型保存所有已注册的 bean 名称。键是 bean 的类型,值是这个类型对应的所有 bean 名称的数组。这使得 Spring 容器可以通过类型快速查找所有匹配的 bean 名称。
      private final Map<Class<?>, String[]> allBeanNamesByType;
    //只存储单例 bean 的名称
      private final Map<Class<?>, String[]> singletonBeanNamesByType;
    //这是一个存储所有已注册的 bean 名称的 List
      private volatile List<String> beanDefinitionNames;
    //这是一个存储手动注册的单例 bean 名称的 Set。手动注册的单例是指通过 registerSingleton 方法直接注入到容器中的 bean,而不是通过 BeanDefinition 创建的 bean。它也是 volatile 的,确保在并发环境下的安全访问
      private volatile Set<String> manualSingletonNames;
      @Nullable
    //这是一个缓存字段,用于存储 "冻结" 的 bean 名称数组。冻结状态表示容器已经准备好进行 bean 创建,所有的 BeanDefinition 都不能再被修改
      private volatile String[] frozenBeanDefinitionNames;
    //这是一个布尔值,表示容器的配置是否已经冻结。冻结配置意味着所有 BeanDefinition 都已经加载完毕,容器进入了只读模式。冻结配置后,容器会跳过许多不必要的检查和处理,从而提高性能。
      private volatile boolean configurationFrozen;
    

    既然来了解beanfactory我们先来看看注册beandefinition这个方法:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    // 验证该 BeanDefinition 的合法性,比如是否有构造函数、属性等配置问题
        if (beanDefinition instanceof AbstractBeanDefinition abd) {
            try {
                abd.validate();
            } catch (BeanDefinitionValidationException var8) {
                BeanDefinitionValidationException ex = var8;
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex);
            }
        }
        // DefaultListableBeanFactory 定义了 private final Map<String, BeanDefinition> beanDefinitionMap;
        BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
      // 如果该 BeanDefinition 已经存在,处理覆盖的情况
        if (existingDefinition != null) {
          //就是看allowBeanDefinitionOverriding这个值默认为true
            if (!this.isBeanDefinitionOverridable(beanName)) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            }
        // 如果现有的定义的角色小于新的定义,记录覆盖信息
            if (existingDefinition.getRole() < beanDefinition.getRole()) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
              // // 如果新的定义和现有定义不同,输出调试日志,表示进行了覆盖
            } else if (!beanDefinition.equals(existingDefinition)) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
                }
              // 如果新的定义与现有定义完全相同,输出 trace 日志,表示没有实际改变
            } else if (this.logger.isTraceEnabled()) {
                this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
// 将新的 beanDefinition 覆盖到 map 中
            this.beanDefinitionMap.put(beanName, beanDefinition);
        } else {
          // 如果当前 bean 名称是一个别名(alias),则处理别名冲突
            if (this.isAlias(beanName)) {
                String aliasedName = this.canonicalName(beanName);
               // 检查别名的目标 bean 是否允许覆盖
                if (!this.isBeanDefinitionOverridable(aliasedName)) {
                      // 如果别名已经存在 BeanDefinition,则抛出异常

                    if (this.containsBeanDefinition(aliasedName)) {
                        throw new BeanDefinitionOverrideException(beanName, beanDefinition, this.getBeanDefinition(aliasedName));
                    }

                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition for bean '" + beanName + "' since there is already an alias for bean '" + aliasedName + "' bound.");
                }
                                // 删除别名
                this.removeAlias(beanName);
            }
                     // 检查容器是否已经开始创建 bean(即容器是否已经启动),如果已经启动则进行同步操作

            if (this.hasBeanCreationStarted()) {
                synchronized(this.beanDefinitionMap) {
                  // 将新的 BeanDefinition 放入 beanDefinitionMap 中
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                      // 创建一个新的 list 并添加新的 beanName,避免并发问题
                    List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                   // 删除手动注册的单例
                    this.removeManualSingletonName(beanName);
                }
            } else {
                 // 如果容器还没有启动,直接将 beanDefinition 放入 map 中并添加到 list 中

                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.removeManualSingletonName(beanName);
            }
                    // 冻结 beanDefinitionNames 的缓存,表示该集合已经被更新

            this.frozenBeanDefinitionNames = null;
        }
            // 如果没有旧的定义,并且当前 bean 不是单例,检查是否需要清空类型缓存

        if (existingDefinition == null && !this.containsSingleton(beanName)) {
                  // 如果容器已经冻结了配置,则清理按类型的缓存

            if (this.isConfigurationFrozen()) {
                this.clearByTypeCache();
            }
        } else {
                  // 如果存在旧的定义,重置该 bean 的定义
            this.resetBeanDefinition(beanName);
        }

    }

参数验证与 BeanDefinition 验证

  • Assert.hasText(beanName)Assert.notNull(beanDefinition) 用来验证参数的合法性。
  • 如果 beanDefinitionAbstractBeanDefinition 的实例(通常是,因为大多数 BeanDefinition 是其子类),调用 validate() 方法对 bean 定义进行合法性验证。

处理已有 BeanDefinition 的覆盖

  • 如果当前已经存在一个同名的BeanDefinition,则会进行一系列检查:

  • 是否允许覆盖现有的 bean 定义,如果不允许则抛出异常。

  • 如果新旧定义不相同,则输出不同级别的日志信息。

  • 将新的定义覆盖旧的定义。

别名处理

  • 如果 beanName 是一个别名,则检查别名所指向的 bean,避免冲突。
  • 如果有别名冲突,删除该别名。

容器状态检查

  • 如果容器已经开始创建 bean(说明容器正在运行),那么需要对 beanDefinitionMap 进行同步操作,以避免并发问题。
  • 如果容器还未启动,则直接更新 beanDefinitionMapbeanDefinitionNames

缓存与配置冻结

  • 如果当前容器配置已经冻结(isConfigurationFrozen()),则清理按类型缓存。
  • 如果已经存在旧定义或是单例 bean,则调用 resetBeanDefinition() 重置该 bean 定义。

再来看看BeanDefinition的字段:

private volatile Object beanClass; 
// 用于保存 bean 的类信息。它可以是 Class 对象,也可以是类名字符串。使用 volatile 以确保线程安全。

@Nullable
private String scope; 
// 描述 bean 的作用域。可能的值包括 "singleton"(默认)和 "prototype" 等。如果为 null,表示使用默认的 singleton 作用域。

private boolean abstractFlag; 
// 指示这个 bean 定义是否是抽象的。如果为 true,则这个 bean 不能被实例化,只能被子类继承。

@Nullable
private Boolean lazyInit; 
// 表示是否懒加载。如果为 true,Spring 容器会在第一次请求时才初始化该 bean;否则在容器启动时初始化。

private int autowireMode; 
// 自动装配模式,表示依赖注入的方式。可能的值包括 AutowireCapableBeanFactory.NO_AUTOWIRE(不自动装配)、BY_NAME(通过名称自动装配)、BY_TYPE(通过类型自动装配)等。

private int dependencyCheck; 
// 检查依赖项的模式,可能的值包括 NONE(不检查依赖)、OBJECTS、SIMPLE(检查简单属性,如基本类型和字符串)等。

@Nullable
private String[] dependsOn; 
// 该 bean 所依赖的其他 bean 名称列表。Spring 容器会确保这些依赖先初始化。

private boolean autowireCandidate; 
// 标识该 bean 是否是自动装配的候选者。如果为 false,则该 bean 不会在自动装配中被考虑。

private boolean primary; 
// 如果容器中有多个相同类型的 bean,primary 表示是否优先使用这个 bean。true 表示优先使用。

private final Map<String, AutowireCandidateQualifier> qualifiers; 
// 存储用于自动装配限定的条件,通过这些限定符可以进一步指定自动装配的细节。

@Nullable
private Supplier<?> instanceSupplier; 
// 用于提供 bean 的实例化逻辑的 Supplier。可以通过这个 Supplier 提供自定义的实例化逻辑。

private boolean nonPublicAccessAllowed; 
// 是否允许访问非 public 的构造函数和方法。如果为 true,Spring 容器可以通过反射访问非 public 的构造函数和方法。

private boolean lenientConstructorResolution; 
// 是否宽松地解析构造函数。如果为 true,Spring 容器在找不到完全匹配的构造函数时会尝试使用最接近的构造函数。

@Nullable
private String factoryBeanName; 
// 指定创建这个 bean 的工厂 bean 名称。如果该 bean 是通过工厂 bean 创建的,那么会存储工厂 bean 的名称。

@Nullable
private String factoryMethodName; 
// 指定工厂 bean 用于创建这个 bean 的工厂方法名。

@Nullable
private ConstructorArgumentValues constructorArgumentValues; 
// 构造函数参数的值,用于在创建 bean 时传递给构造函数。

@Nullable
private MutablePropertyValues propertyValues; 
// 用于存储 bean 的属性值,这些属性会通过 setter 方法或者字段注入到 bean 中。

private MethodOverrides methodOverrides; 
// 代表方法的重写信息,主要用于支持运行时方法替换,例如通过 `lookup-method` 和 `replace-method` 标签配置的行为。

@Nullable
private String[] initMethodNames; 
// 定义 bean 的初始化方法名称列表。Spring 会在 bean 创建之后调用这些方法。

@Nullable
private String[] destroyMethodNames; 
// 定义 bean 的销毁方法名称列表。Spring 会在 bean 销毁之前调用这些方法。

private boolean enforceInitMethod; 
// 是否强制执行初始化方法。如果为 true,初始化方法必须存在,否则抛出异常。

private boolean enforceDestroyMethod; 
// 是否强制执行销毁方法。如果为 true,销毁方法必须存在,否则抛出异常。

private boolean synthetic; 
// 表示这个 bean 是否是框架内部使用的合成 bean。如果为 true,表明这是一个特殊的 bean,通常不会被应用程序直接使用。

private int role; 
// bean 的角色,可能的值包括 ROLE_APPLICATION(应用程序定义的 bean)、ROLE_SUPPORT(部分内部支持 bean)、ROLE_INFRASTRUCTURE(完全由框架使用的内部 bean)。

@Nullable
private String description; 
// bean 的描述信息,通常用于文档化目的。

@Nullable
private Resource resource; 
// bean 定义的来源资源,用于描述 bean 是从哪里加载的(例如 XML 文件或注解配置类)。
```java
 //手动创建BeanDefinition
 // 创建一个 GenericBeanDefinition
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(MyBean.class);  // 设置 bean 的类
        beanDefinition.setScope("singleton");      // 设置作用域(例如 singleton)
        beanDefinition.getPropertyValues().add("name", "Manual Bean");  // 设置属性值
```java
  // 通过 BeanDefinitionBuilder 创建一个 BeanDefinition
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);

        // 添加属性值(可以通过 setter 方法注入)
        builder.addPropertyValue("name", "Test Bean");

        // 设置自动装配模式(例如:按类型自动装配)
        builder.setAutowireMode(BeanDefinition.AUTOWIRE_BY_TYPE);

        // 设置作用域为 prototype
        builder.setScope("prototype");

        // 创建 BeanDefinition
        BeanDefinition beanDefinition = builder.getBeanDefinition();

模仿实现一个beanfactory:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Bean {
}
```
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
}
```
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Configuration {
}
```java
public class BeanDefinition {
    private Class<?> beanClass;
    private Method factoryMethod;

    public BeanDefinition(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    public BeanDefinition(Class<?> beanClass, Method factoryMethod) {
        this.beanClass = beanClass;
        this.factoryMethod = factoryMethod;
    }

    public Class<?> getBeanClass() {
        return beanClass;
    }

    public Method getFactoryMethod() {
        return factoryMethod;
    }
}
```
@Component
public class MyRepository {
}
```java
@Component
public class MyService {

        private final MyRepository myRepository;

        public MyService(MyRepository myRepository) {
            this.myRepository = myRepository;
        }

        public void performService() {
            System.out.println("Service is performing...");
        }


}
```java
@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyService(myRepository());
    }

    @Bean
    public MyRepository myRepository() {
        return new MyRepository();
    }
}
```java
//模仿一个AnnotationConfigApplicationContext
        private Map<String, Object> beanMap = new HashMap<>();
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        // 扫描并注册 Bean
        for (Class<?> configClass : annotatedClasses) {
            registerBeanDefinitions(configClass);
        }
        // 实例化所有 Bean
        for (String beanName : beanDefinitionMap.keySet()) {
            createBean(beanName);
        }
    }

    private void registerBeanDefinitions(Class<?> configClass) {
        if (configClass.isAnnotationPresent(Configuration.class)) {
            for (Method method : configClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(Bean.class)) {
                    String beanName = method.getName();
                    beanDefinitionMap.put(beanName, new BeanDefinition(configClass, method));
                }
            }
        }
        // 组件扫描(简化处理)
        for (Class<?> clazz : configClass.getDeclaredClasses()) {
            if (clazz.isAnnotationPresent(Component.class)) {
                String beanName = decapitalize(clazz.getSimpleName());
                beanDefinitionMap.put(beanName, new BeanDefinition(clazz));
            }
        }
    }

    private void createBean(String beanName) {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition.getFactoryMethod() != null) {
            try {
                Object bean = beanDefinition.getFactoryMethod().invoke(beanDefinition.getBeanClass().newInstance());
                beanMap.put(beanName, bean);
            } catch (Exception e) {
                throw new RuntimeException("Failed to create bean", e);
            }
        } else {
            try {
                Object bean = beanDefinition.getBeanClass().newInstance();
                beanMap.put(beanName, bean);
            } catch (Exception e) {
                throw new RuntimeException("Failed to create bean", e);
            }
        }
    }

    public <T> T getBean(Class<T> requiredType) {
        return requiredType.cast(beanMap.values().stream()
                .filter(bean -> requiredType.isInstance(bean))
                .findFirst()
                .orElseThrow(() -> new RuntimeException("No bean found")));
    }

    private String decapitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }

完成对beanfactory学习,下面我们来了解一下ApplicationContext:

ApplicationContext 继承自 BeanFactory,并在此基础上扩展了大量功能以下是 ApplicationContext 提供的核心功能:

继承 BeanFactoryApplicationContext 继承了 BeanFactory,因此具备了所有的 Bean 管理功能,如 Bean 的加载、实例化、依赖注入等。

事件机制:提供了发布和监听事件的能力(通过 ApplicationEventApplicationListener)。

国际化支持:通过 MessageSource 接口提供国际化消息的解析功能。

资源加载:通过 ResourceLoader 提供加载外部资源(如文件、URL)的功能。

自动装配:支持基于注解的自动装配(如 @Autowired)。

环境管理:通过 Environment 接口管理环境变量和属性文件。

主要的实现类包括:

ClassPathXmlApplicationContext:从类路径加载 XML 配置文件。

FileSystemXmlApplicationContext:从文件系统加载 XML 配置文件。

AnnotationConfigApplicationContext:基于 Java 配置类和注解的方式加载配置

选择在springboot启动类使用的AnnotationConfigApplicationContext来学习一下,下面是他的类图:

AnnotationConfigApplicationContext

ApplicationContext 的初始化过程可以分为以下几个步骤:

  1. 创建 ApplicationContext 实例:通常由具体实现类如 ClassPathXmlApplicationContextAnnotationConfigApplicationContext 来创建。
  2. 加载配置文件或配置类:解析配置文件(如 XML)或配置类(如 Java 类),生成 BeanDefinition
  3. 注册 BeanFactoryPostProcessor:在加载完 BeanDefinition 后,Spring 会注册并执行 BeanFactoryPostProcessor,允许在 Bean 实例化之前对 BeanDefinition 进行修改。
  4. 初始化单例 Bean:在容器刷新时,会调用 preInstantiateSingletons() 方法,初始化所有非懒加载的单例 Bean。
  5. 注册 ApplicationListener:在 ApplicationContext 启动过程中,会注册所有的事件监听器,并且在事件发布时通知相应的监听器。
  6. 发布 ContextRefreshedEvent 事件:容器启动完毕后,会发布 ContextRefreshedEvent 事件,所有监听器会收到通知。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 1. 准备上下文环境
            prepareRefresh();

            // 2. 初始化 BeanFactory 并加载 Bean 定义
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 3. 对 BeanFactory 进行定制化,例如添加 BeanPostProcessor
            prepareBeanFactory(beanFactory);

            try {
                // 4. 子类扩展点,留给子类实现,用于在 BeanFactory 标准初始化之后,进行定制化的扩展。
                postProcessBeanFactory(beanFactory);

                // 5. 执行 BeanFactoryPostProcessor,
                invokeBeanFactoryPostProcessors(beanFactory);

                // 6. 注册 BeanPostProcessor
                registerBeanPostProcessors(beanFactory);

                // 7. 初始化消息源(国际化功能)
                initMessageSource();

                // 8. 初始化事件机制
                initApplicationEventMulticaster();

                // 9. 子类扩展点:用于特殊 Bean 的初始化,提供给子类实现的扩展点,允许在刷新上下文时执行自定义逻辑。
                onRefresh();

                // 10. 注册监听器
                registerListeners();

                // 11. 初始化所有非懒加载的单例 Bean
                finishBeanFactoryInitialization(beanFactory);

                // 12. 完成刷新,发布事件
                finishRefresh();
            }
            catch (BeansException ex) {
                // 若出错,销毁已创建的单例 Bean
                destroyBeans();
                cancelRefresh(ex);
                throw ex;
            }
        }
    }
}
```java
/**
启动时间:记录容器的启动时间,以支持生命周期相关的功能。
环境验证:调用 getEnvironment().validateRequiredProperties() 方法,验证必要的环境属性是否存在。
事件机制准备:初始化早期的事件监听器和事件集合。

**/
protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    if (this.logger.isInfoEnabled()) {
        this.logger.info("Refreshing " + this);
    }

    // 初始化上下文环境属性
    initPropertySources();

    // 校验必要的属性
    getEnvironment().validateRequiredProperties();

    // 初始化 earlyApplicationListeners、earlyApplicationEvents 等
    this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    this.earlyApplicationEvents = new LinkedHashSet<>();
}
```java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 关闭之前的 BeanFactory(如果有)
    refreshBeanFactory();

    // 获取新的 BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();

    return beanFactory;
}
```java
/**
设置类加载器:为 BeanFactory 设置类加载器,确保能够正确加载 Bean 类。
表达式解析:配置 BeanExpressionResolver,支持表达式语言(如 SpEL)的解析。
注册 BeanPostProcessor:注册一个 ApplicationContextAwareProcessor,用于在 Bean 实例化后进行自定义处理。
忽略依赖接口:忽略一些特殊的依赖接口,这些接口会在 Bean 初始化时自动注入。
注册默认依赖:如 Environment 和 BeanFactory,这些依赖将自动注入到需要的 Bean 中。
**/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置类加载器
    beanFactory.setBeanClassLoader(getClassLoader());

    // 设置表达式语言处理器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

    // 添加 PropertyEditor 支持
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 添加 BeanPostProcessor
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    // 忽略一些依赖接口
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // 注册一些默认的依赖,如 Environment
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
}
```java
protected void finishRefresh() {
    // 清除上下文缓存
    clearResourceCaches();

    // 初始化生命周期管理器
    initLifecycleProcessor();

    // 启动所有的生命周期 Bean
    getLifecycleProcessor().onRefresh();

    // 发布容器刷新完成事件
    publishEvent(new ContextRefreshedEvent(this));

    // 注册JMX相关的内容(可选)
    LiveBeansView.registerApplicationContext(this);
}

设计中使用了多种设计模式:

  • 工厂模式(Factory Pattern)ApplicationContext 通过工厂模式来创建和管理 Bean 对象。

  • 模板方法模式(Template Method Pattern)AbstractApplicationContext 中定义了 refresh() 方法,具体实现类可以在这个模板方法中定制容器的启动过程。

  • 观察者模式(Observer Pattern):通过事件机制,实现了监听器对事件的观察与响应。

  • 策略模式(Strategy Pattern)BeanPostProcessorBeanFactoryPostProcessor 的实现允许用户自定义 Bean 的创建和初始化逻辑。

ApplicationContext` 的设计遵循了一些重要的面向对象设计原则:

  • 单一职责原则 (SRP)ApplicationContext 本身不直接管理 Bean,而是通过 BeanFactory 来实现,这样确保了每个类只承担一个职责。
  • 开放-封闭原则 (OCP)ApplicationContext 提供了多种扩展点,如 BeanPostProcessorBeanFactoryPostProcessorApplicationListener,允许用户在不修改框架代码的情况下,定制容器的行为。
  • 依赖倒置原则 (DIP):高层次的 ApplicationContext 依赖于抽象的 BeanFactory,而不是具体的实现类,这使得 ApplicationContext 可以灵活地支持不同类型的 Bean 管理方式。

BeanPostProcessor 和 BeanFactoryPostProcessor

BeanPostProcessor 接口允许在 Bean 实例化之后、初始化之前和之后对 Bean 进行修改。它的典型用途包括:

  • 设置代理对象。
  • 修改属性值。
  • 检查特定条件

核心方法:

  • postProcessBeforeInitialization(Object bean, String beanName): 在 Bean 初始化之前调用。
  • postProcessAfterInitialization(Object bean, String beanName): 在 Bean 初始化之后调用。

BeanFactoryPostProcessor 接口允许在容器加载 Bean 定义后但在实例化 Bean 之前,对 BeanDefinition 进行修改。可以用来动态修改 Bean 配置。

核心方法:

  • postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory): 允许对 BeanFactory 的配置进行定制。

一些常用的beanPostprocessor :

CommonAnnotationBeanPostProcessor

  • 处理 Java EE 标准中的注解:@PostConstruct@PreDestroy@Resource
  • 确保这些注解在 Spring 管理的 Bean 上正确执行

AutowiredAnnotationBeanPostProcessor

  • 处理 @Autowired@Value@Inject 注解
  • 实现依赖注入的核心,自动注入依赖或外部化配置

RequiredAnnotationBeanPostProcessor

  • 处理 @Required 注解
  • 确保在 Bean 初始化时,所有使用 @Required 标注的属性都已被设置

InstantiationAwareBeanPostProcessor

  • 扩展了 BeanPostProcessor 的功能
  • 允许在 Bean 实例化之前进行操作,以及在属性注入阶段进行干预

ApplicationContextAwareProcessor

  • 处理实现了 ApplicationContextAware 接口的 Bean
  • 确保在 Bean 初始化过程中注入 Spring 容器的上下文(ApplicationContext

AspectJAwareAdvisorAutoProxyCreator

  • 用于 AOP 的实现,自动代理所有基于 AspectJ 的切面
  • 检查是否需要为当前 Bean 创建代理对象,应用相关通知器(Advisor)

InitDestroyAnnotationBeanPostProcessor

  • 处理自定义的初始化和销毁方法
  • 允许使用自定义注解指定 Bean 初始化后和销毁前需要执行的特定方法

PersistenceAnnotationBeanPostProcessor

  • 处理 JPA 中的 @PersistenceContext@PersistenceUnit 注解
  • 自动注入 EntityManagerEntityManagerFactory,用于数据库操作

ScheduledAnnotationBeanPostProcessor

  • 处理 @Scheduled 注解,用于定时任务的执行
  • 注册定时任务并由 Spring 的任务调度器管理

ConfigurationClassPostProcessor

处理 @Configuration 注解ConfigurationClassPostProcessor 会扫描并解析标注了 @Configuration 的类,将其作为配置类来处理。这些配置类通常用来定义 @Bean 方法,并可以包括其他注解如 @ComponentScan@Import

解析 @Bean 方法:在解析 @Configuration 类时,ConfigurationClassPostProcessor 会识别并处理 @Bean 注解的方法,将这些方法返回的对象作为 Spring 容器中的 Bean 进行注册。

代理增强:对于标注了 @Configuration 的类,Spring 可能会对其生成 CGLIB 代理,以确保 @Bean 方法之间的调用能正确处理单例模式。

ImportAwareBeanPostProcessor

处理 @Import 注解ImportAwareBeanPostProcessor 处理那些实现了 ImportAware 接口的类,使它们能够感知它们是通过 @Import 注解被引入的,以及引入它们的配置类。

环境感知:通过 ImportAware 接口,配置类可以获取到引入它们的其他配置类的信息,这有助于动态调整配置或逻辑。

@Component
class MyBean implements InitializingBean, DisposableBean {

    private String message;

    public MyBean() {
        System.out.println("Bean实例化");
    }

    public void setMessage(String message) {
        this.message = message;
        System.out.println("属性设置:" + message);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("初始化方法:调用 afterPropertiesSet()");
    }

    public void customInit() {
        System.out.println("自定义初始化方法:customInit()");
    }

    public void sayHello() {
        System.out.println("Hello from MyBean: " + message);
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("销毁方法:调用 destroy()");
    }

    public void customDestroy() {
        System.out.println("自定义销毁方法:customDestroy()");
    }
}
```java
class MyApplicationListener implements ApplicationListener<MyEvent> {

       @Override
        public void onApplicationEvent(MyEvent event) {
            // 在应用程序上下文刷新时执行的逻辑
            System.out.println("Application context has been refreshed!!!"+event.getEventData());
        }
    }

    class MyEvent extends ApplicationEvent {


        private String eventData;

        public MyEvent(Object source, String eventData) {
            super(source);
            this.eventData = eventData;
        }

        public String getEventData() {
            return eventData;
        }
    }
```java

        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("ryu",MyBean.class,() -> new MyBean());

        BeanFactoryPostProcessor beanFactoryPostProcessor = new BeanFactoryPostProcessor() {
            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                System.out.println("BeanFactoryPostProcessor");
                MyBean bean = (MyBean) beanFactory.getBean("ryu");
                bean.sayHello();
            }
        };
        DefaultListableBeanFactory defaultListableBeanFactory = context.getDefaultListableBeanFactory();
        defaultListableBeanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if(bean.getClass()==MyBean.class){
                    System.out.println("之前:"+"BeanPostProcessor");
                }
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if(bean.getClass()==MyBean.class){
                    System.out.println("之后:"+"BeanPostProcessor");
                }
                return bean;
            }
        });
        context.addBeanFactoryPostProcessor(beanFactoryPostProcessor);
        context.setApplicationStartup(ApplicationStartup.DEFAULT);
        context.addApplicationListener(new MyApplicationListener());

        context.refresh();
        context.publishEvent(new MyEvent(this, "CustomEventData"));

        MyBean bean = context.getBean(MyBean.class);
        MyBean bean2 = context.getBean(MyBean.class);
        System.out.println(bean == bean2);
        context.close();

Spring 容器的启动流程

  1. 配置解析:Spring 解析配置文件(如 XML 或 Java 配置类),并读取所有的 BeanDefinition

  2. BeanDefinition 注册:将解析得到的 BeanDefinition 注册到容器中。BeanDefinition 是对 Bean 的描述信息,包括类名、作用域、依赖等。

  3. Bean 初始化

  4. 单例模式ApplicationContext 会在启动时创建所有的单例 Bean 实例。

  5. 原型模式:每次请求时才会创建新的 Bean 实例。

  6. 依赖注入:Spring 使用构造函数注入、setter 注入或注解注入,将依赖的 Bean 注入到目标对象中。

  7. 后处理器调用:如果注册了 BeanPostProcessorBeanFactoryPostProcessor,Spring 会在 Bean 实例化之前和之后调用这些后处理器,以便进行自定义逻辑处理。

  8. Bean 就绪:所有 Bean 都完成初始化和依赖注入后,Spring 容器准备就绪,可以接收请求或执行应用逻辑。

Bean 的生命周期

1. Bean 实例化

  • 过程:Spring 根据配置(例如 XML 配置、注解、Java 配置类等)实例化 Bean。这个阶段通过调用 Bean 的构造函数创建 Bean 对象。
  • 相关接口BeanFactoryApplicationContext 会调用 Bean 的构造函数来创建实例。

2. 属性填充

  • 过程:在实例化之后,Spring 会注入 Bean 的依赖项。这包括通过构造函数注入、setter 方法注入或字段注入的方式来设置 Bean 的属性。
  • 相关注解@Autowired@Value 等。

3. 初始化

  • 过程:在所有依赖项注入完成后,Spring 会执行 Bean 的初始化过程。如果 Bean 实现了 InitializingBean 接口,则会调用 afterPropertiesSet() 方法。此外,还可以通过 @PostConstruct 注解指定初始化方法。
  • 相关接口/注解InitializingBean@PostConstructinit-method(在 XML 配置中)。

4. 使用

  • 过程:Bean 现在已经完全初始化,可以被应用程序使用。此阶段 Bean 处于活动状态,可以处理业务逻辑。

5. 销毁

  • 过程:当 Spring 容器关闭或 Bean 不再需要时,Bean 会被销毁。在销毁之前,Spring 会执行清理操作。如果 Bean 实现了 DisposableBean 接口,则会调用 destroy() 方法。此外,可以通过 @PreDestroy 注解指定销毁方法。

  • 相关接口/注解DisposableBean@PreDestroydestroy-method(在 XML 配置中)。

    Bean的循环依赖

循环依赖发生在两个或多个 Bean 之间存在相互依赖的情况。例如,Bean A 依赖于 Bean B,同时 Bean B 也依赖于 Bean A。Spring 需要解决这种情况,以确保 Bean 的正确创建和依赖注入。

构造函数注入的循环依赖

  • 问题:构造函数注入的循环依赖无法处理,因为 Spring 无法在 Bean 的构造函数中创建出完整的实例。在 Bean A 的构造函数中需要 Bean B,而 Bean B 的构造函数中又需要 Bean A,这种情况会导致死锁或错误。
  • 解决方案:通常推荐避免使用构造函数注入来处理循环依赖。可以使用 setter 注入或字段注入来替代,这样 Spring 可以在实例化 Bean 后再注入依赖项,从而解决循环依赖问题。

Setter 注入的循环依赖

Spring 能够处理 setter 注入的循环依赖,利用三级缓存机制来解决这个问题。具体的机制如下:

三级缓存机制

  1. 一级缓存(singletonObjects

  2. 内容:存储完全初始化好的 Bean 实例。Bean 在完全创建并完成依赖注入后会被放入这里。

  3. 作用:提供对完全初始化的 Bean 的访问。

  4. 二级缓存(earlySingletonObjects

  5. 内容:存储尚未完成初始化但已被实例化的 Bean。这些 Bean 的实例化完成,但可能还没有完全注入依赖项。

  6. 作用:允许在依赖注入过程中解决循环依赖。由于 Bean 尚未完成初始化,Spring 可以提供部分创建的 Bean 实例给其他 Bean 的注入过程。

  7. 三级缓存(singletonFactories

  8. 内容:存储 ObjectFactory 实例,这些实例负责创建 Bean 实例。这里存储的是用来创建 Bean 的工厂对象,而不是实际的 Bean 实例。

  9. 作用:允许 Spring 在 Bean 的实例化过程中将其注册到缓存中,从而处理依赖注入。

解决循环依赖的流程:

  1. 创建 Bean A 和 Bean B 的 ObjectFactory

    • 三级缓存 (singletonFactories)

      • Spring 为 Bean A 和 Bean B 分别创建 ObjectFactory 对象。这些 ObjectFactory 对象负责延迟创建 Bean 实例,直到其所有依赖项都准备好。
      • 这些 ObjectFactory 对象被放置在三级缓存中,等待完成依赖注入后再创建 Bean 实例。
  2. 部分创建的 Bean 存储在二级缓存中

    • 二级缓存 (earlySingletonObjects)

      • Spring 将尚未完全初始化的 Bean 实例(即 Bean B)存储在二级缓存中。这时 Bean B 已经创建,但尚未完成所有的依赖注入。
      • 当 Bean A 需要 Bean B 时,Spring 从二级缓存中获取 Bean B 的部分创建实例。
  3. 解决循环依赖

    • Bean A 的实例

      • Bean A 依赖于 Bean B。由于 Bean B 已经被部分创建并存储在二级缓存中,Spring 可以将 Bean B 的部分实例注入到 Bean A 中。
    • Bean B 的实例

      • Bean B 依赖于 Bean A。Spring 将 Bean A 的 ObjectFactory 放入三级缓存中,以便在 Bean A 完全初始化后创建 Bean A 的实例,并完成 Bean B 的初始化。
  4. 完成 Bean 的初始化

    • 完成 Bean A 和 Bean B 的初始化

      • 一旦 Bean A 和 Bean B 的所有依赖注入和初始化操作完成后,它们会被移到一级缓存 (singletonObjects) 中。
      • Bean A 和 Bean B 的实例现在都完全初始化,并且可以正常使用。