SpringIoc源码(六)- ApplicationContext(二)- refresh(obtainFreshBeanFactory和StandardEnvironment)

本文深入探讨Spring框架的Ioc容器初始化过程,详细分析AbstractApplicationContext的refresh方法,包括prepareRefresh、obtainFreshBeanFactory等关键步骤,以及StandardEnvironment、PropertyResolver等核心组件的作用。

目录

1、StandardEnvironment

1)、PropertyResolver(Property相关处理)

2)、Environment(Spring profiles相关处理)

3)、ConfigurablePropertyResolver(类型转换相关ConversionService)

4)、ConfigurableEnvironment

5)、AbstractEnvironment

6)、StandardEnvironment

2、refresh方法

1)、prepareRefresh

2)、obtainFreshBeanFactory

1、hasBeanFactory

2、createBeanFactory

3、customizeBeanFactory

4、loadBeanDefinitions


  SpringIoc源码,主要的核心是AbstractApplicationContext的refresh方法,所以一切还是回到ClassPathXMLApplicationContext开始

new ClassPathXmlApplicationContext("spring-bean.xml").getBean("kevin");
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, 
    @Nullable ApplicationContext parent) throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

        一般很少使用父ApplicationContext,所以忽略。 setConfigLocations方法

public void setConfigLocations(@Nullable String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

循环处理每个location字符串,继续:

protected String resolvePath(String path) {
    return getEnvironment().resolveRequiredPlaceholders(path);
}

    在这里初始化了每个Spring容器的Environment,这个也是Spring Boot actuator的基础。

public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
    return new StandardEnvironment();
}

1、StandardEnvironment

    个人觉得StandardEnvironment还是比较重要的,我们可以从中获取到很多开发时候需要的属性等。

1)、PropertyResolver(Property相关处理)

public interface PropertyResolver {

    boolean containsProperty(String key);

    @Nullable
    String getProperty(String key);

    String getProperty(String key, String defaultValue);

    @Nullable
    <T> T getProperty(String key, Class<T> targetType);

    <T> T getProperty(String key, Class<T> targetType, T defaultValue);

    String getRequiredProperty(String key) throws IllegalStateException;

    <T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException;

    String resolvePlaceholders(String text);

    String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
}

2)、Environment(Spring profiles相关处理)

public interface Environment extends PropertyResolver {
    String[] getActiveProfiles();

    String[] getDefaultProfiles();

    @Deprecated
    boolean acceptsProfiles(String... profiles);

    boolean acceptsProfiles(Profiles profiles);
}

3)、ConfigurablePropertyResolver(类型转换相关ConversionService)

    比如很少时候,Date和字符串的转换,数字的转换等会使用比较多。

public interface ConfigurablePropertyResolver extends PropertyResolver {

    ConfigurableConversionService getConversionService();

    void setConversionService(ConfigurableConversionService conversionService);

    void setPlaceholderPrefix(String placeholderPrefix);

    void setPlaceholderSuffix(String placeholderSuffix);

    void setValueSeparator(@Nullable String valueSeparator);

    void setIgnoreUnresolvableNestedPlaceholders(boolean 
        ignoreUnresolvableNestedPlaceholders);

    void setRequiredProperties(String... requiredProperties);

    void validateRequiredProperties() throws MissingRequiredPropertiesException;
}

4)、ConfigurableEnvironment

public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {

    void setActiveProfiles(String... profiles);

    void addActiveProfile(String profile);

    void setDefaultProfiles(String... profiles);

    MutablePropertySources getPropertySources();

    Map<String, Object> getSystemProperties();

    Map<String, Object> getSystemEnvironment();
    // 设置父ApplicationContext时回调用
    void merge(ConfigurableEnvironment parent);
}

5)、AbstractEnvironment

    以上所有的接口声明基本都在AbstractEnvironment中完成,并且其的无参构造中回调了子类实现的customizePropertySources方法。

public abstract class AbstractEnvironment implements ConfigurableEnvironment {

    public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore";

    public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";

    public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";

    protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default";
    // 当前激活的profiles列表 
    private final Set<String> activeProfiles = new LinkedHashSet<>();
    // 默认的profiles为RESERVED_DEFAULT_PROFILE_NAME(字符串 default)
    private final Set<String> defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles());
    // 初始化MutablePropertySources类型
    private final MutablePropertySources propertySources = new MutablePropertySources();
    // 初始化PropertySourcesPropertyResolver类型
    private final ConfigurablePropertyResolver propertyResolver =
            new PropertySourcesPropertyResolver(this.propertySources);

    public AbstractEnvironment() {
        customizePropertySources(this.propertySources);
    }
     // 省略其他Property相关的方法等。
}

6)、StandardEnvironment

    StandardEnvironment初始化,会父类无参构造,然后回调StandardEnvironment的customizePropertySources方法:

protected void customizePropertySources(MutablePropertySources propertySources) {
    propertySources.addLast(new PropertiesPropertySource(
        SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
    propertySources.addLast(new SystemEnvironmentPropertySource(
        SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

    将值回置到父类PropertySourcesPropertyResolver中的MutablePropertySources中。看看具体实现:

public Map<String, Object> getSystemProperties() {
    return (Map) System.getProperties();
}
public Map<String, Object> getSystemEnvironment() {
    return (Map) System.getenv();
}

    都是从System中获取的,是java底层启动时就初始化完成的,只是Spring对其进行了包装。

2、refresh方法

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 准备环境
        prepareRefresh();

        // 初始化BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // BeanFactory初始化一些东西
        prepareBeanFactory(beanFactory);

        try {
            // 模板方法允许当前AbstractApplicationContext子类,对BeanFactory进行一些改造
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

1)、prepareRefresh

protected void prepareRefresh() {
    // Switch to active. 主要是实现Lifecycle接口的方法,容器生命周期相关
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);
    
    // 初始化容器的属性,主要是Web类型的ApplicationContext调用
    // WebApplicationContextUtils#initServletPropertySources方法
    initPropertySources();

    // 验证属性信息会调用上面初始化的 AbstractEnvironment内部的
    // PropertySourcesPropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();

    // Store pre-refresh ApplicationListeners..., 这里基本都为空,不知道什么时候不为空,后续验证
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
        // Reset local application listeners to pre-refresh state.
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

    之前是因为ClassPathXmlApplicatonContext类型,在refresh之前进行了setLocations,将StandardEnvironment(或其子类)初始化了,否则当前才会进行初始化。

2)、obtainFreshBeanFactory

    初始化BeanFactory,主要看当前的ApplicationContext的类型,如果是AbstractRefreshableApplicationContext的子类和GenericApplicationContext的子类,实现会不相同。

protected final void refreshBeanFactory() throws BeansException {
    // 如果beanFactory已经初始化了,则进行销毁
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 初始化BeanFactory -> new DefaultListableBeanFactory(getInternalParentBeanFactory());
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        // 留给子类实现
        customizeBeanFactory(beanFactory);
        // 加载BeanDefinition
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        // 省略
    }
}

1、hasBeanFactory

    判断比较简单(this.beanFactory != null),但是如果已经存在,则进行销毁。 之前写东西的时候,用到了相关的销毁,所以映象比较深,进行分析一下。

closeBeanFactory比较简单,将BeanFactory置为null,将id设置为空;

destroyBeans做了很多事,也更深入地理解了BeanFactory的允许机制,内部容器的结构。

protected void destroyBeans() {
    getBeanFactory().destroySingletons();
}

当前的BeanFactory为DefaultListableBeanFactory,那么调用其方法

@Override
public void destroySingletons() {
    super.destroySingletons();
    updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
    clearByTypeCache();
}

分层的思想特别好,各处理各的容器(ConcurrentHashMap)。查看父类DefaultSingletonBeanRegistry的处理:

  • 1)、DefaultSingletonBeanRegistry#destroySingletons
public void destroySingletons() {
    synchronized (this.singletonObjects) {
        this.singletonsCurrentlyInDestruction = true;
    }

    String[] disposableBeanNames;
    synchronized (this.disposableBeans) {
        disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
    }
    for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
        destroySingleton(disposableBeanNames[i]);
    }

    this.containedBeanMap.clear();
    this.dependentBeanMap.clear();
    this.dependenciesForBeanMap.clear();

    clearSingletonCache();
}

如果有实现了DisposableBean接口的,在当前进行销毁处理了很多地方(可想Spring设计的时候还是比较复杂的):

this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
disposableBeans.remove(beanName);
dependentBeanMap.remove(beanName);
containedBeanMap.remove(beanName);
dependenciesForBeanMap.remove(beanName);
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
  • 2)、DefaultListableBeanFactory#destroySingletons
this.allBeanNamesByType.clear();
this.singletonBeanNamesByType.clear();

2、createBeanFactory

protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

    比较简单,但是非常重要,做了很多事,详细参见:SpringIoc源码(二)- BeanFactory(一)- 结构梳理(DefaultListableBeanFactory)

3、customizeBeanFactory

只有 AbstractRefreshableApplicationContext(以及其子类)有实现特殊定制:

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    if (this.allowBeanDefinitionOverriding != null) {
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.allowCircularReferences != null) {
        beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
}

4、loadBeanDefinitions

    当前需要看是哪种类型的ApplicationContext,如果是Spring Boot的(GenericApplicationContext的子类)使用的都会进入到的方法:(只是设置id和检查

protected final void refreshBeanFactory() throws IllegalStateException {
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException(
                "GenericApplicationContext does not support multiple refresh attempts
            : just call 'refresh' once");
    }
    this.beanFactory.setSerializationId(getId());
}

    否则如果当前是AbstractRefreshableApplicationContext的子类,比如当前的ClassPathXmlApplicationContext类型:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}

比较熟悉了,new了一个XmlBeanDefinitionReader,再去

loadBeanDefinitions(beanDefinitionReader);

详细流程参见:SpringIoc源码(三)- BeanFactory(二)- XmlBeanFactory注册BeanDefinition

 

<think>好的,我现在需要帮助用户理解Spring IOC容器的源码实现工作原理。用户之前已经提供了一些相关的引用内容,我需要结合这些内容来组织一个清晰且详细的回答。 首先,我应该先回顾用户提供的引用,找出关键点。引用1提到BeanFactoryApplicationContext是两个核心接口,需要分析它们的源码差异。引用2提到了IoC容器的基本概念、关键接口、bean的生命周期循环依赖的解决方法。引用3提到了事件发布器监听器的初始化,这部分涉及观察者模式。引用4是关于prepareRefresh方法的预处理步骤,包括初始化属性早期事件处理。引用5提到了Bean工厂后置处理器Bean实例化的完成。 接下来,我需要确定回答的结构。通常,源码分析可以从容器启动流程、Bean生命周期管理、核心接口差异、设计模式应用等方面展开。用户的问题比较广泛,所以需要覆盖主要部分,同时保持结构清晰。 第一步,容器启动流程。根据引用4中的prepareRefresh方法,这是刷新前的预处理步骤,包括设置启动时间、状态,初始化属性,验证环境变量,保存早期事件。然后,引用5中的invokeBeanFactoryPostProcessorsfinishBeanFactoryInitialization是后续步骤,处理Bean工厂后置处理器实例化Bean。需要详细说明这些步骤的顺序作用。 第步,Bean的生命周期管理。这里需要结合BeanFactoryApplicationContext的区别,可能涉及Bean的创建、初始化、依赖注入、销毁等阶段。引用2中提到bean的生命周期是一个重点,可能需要详细描述每个阶段涉及的接口方法,比如BeanPostProcessor。 第三步,关键接口分析。BeanFactory作为基础接口,而ApplicationContext扩展了更多功能,如事件发布、国际化等。引用1引用2都提到了这两个接口,需要比较它们的源码功能差异,比如ApplicationContext如何继承BeanFactory并添加额外特性。 第四部分,设计模式的应用。例如,观察者模式在事件处理中的应用,如引用3中的事件发布器监听器的初始化。可能还有工厂模式在Bean创建中的使用,单例模式在Bean作用域中的应用等。 第五部分,解决循环依赖。引用2提到循环依赖是高级特性,需要解释Spring如何通过三级缓存解决这个问题,可能涉及源码中的DefaultSingletonBeanRegistry类中的getSingleton方法及相关处理。 在组织内容时,要确保每个部分都有对应的源码引用解释,例如在容器启动流程中,可以引用prepareRefresh的代码片段,说明其作用。同时,结合用户提供的引用,正确标注引用标识,如[^4]、[^5]等。 另外,用户可能需要示例代码或流程图来辅助理解,但根据问题描述,用户要求的是文本回答,所以需要用清晰的步骤子标题来划分内容。比如使用“1. 容器启动流程”、“2. Bean生命周期管理”等。 最后,生成相关问题,可能需要围绕源码分析、设计模式、具体实现细节等方面提问,例如询问BeanFactoryApplicationContext的区别,或者如何扩展BeanPostProcessor接口。 需要确保回答符合用户的要求:结构清晰,分步骤解释,引用正确,并且使用中文。同时,避免使用Markdown格式,但根据用户提供的示例,可能需要使用代码块来展示源码片段,如引用4中的prepareRefresh方法代码。 现在需要整合这些思路,形成一个连贯的回答,涵盖用户提到的所有关键点,并正确引用提供的参考文献。</think>### Spring IOC 源码分析及详细解读 #### 一、容器启动流程 Spring IOC 容器的启动流程围绕 `ApplicationContext` 的 `refresh()` 方法展开,核心步骤如下: 1. **预处理阶段 (`prepareRefresh()`)** - 记录启动时间,设置容器状态为激活。 - 初始化环境变量配置参数(如 `initPropertySources()`)。 - 验证必要属性是否合法(如 `validateRequiredProperties()`)。 - 准备早期事件存储队列 `earlyApplicationEvents` [^4]。 2. **加载Bean定义 (`obtainFreshBeanFactory()`)** - 创建 `BeanFactory`(默认实现为 `DefaultListableBeanFactory`)。 - 解析 XML 或注解配置,将 Bean 定义注册到 `BeanDefinitionMap` 中。 3. **处理后置处理器 (`invokeBeanFactoryPostProcessors()`)** - 调用 `BeanFactoryPostProcessor` 实现类(如 `ConfigurationClassPostProcessor`),完成配置类解析、`@Bean` 方法解析等[^5]。 4. **初始化事件监听器** - 通过 `initApplicationEventMulticaster()` 初始化事件广播器。 - 通过 `registerListeners()` 注册监听器,支持观察者模式[^3]。 5. **实例化单例Bean (`finishBeanFactoryInitialization()`)** - 遍历 `BeanDefinitionMap`,对非懒加载的单例 Bean 进行实例化、依赖注入初始化[^5]。 --- #### 、Bean生命周期管理 Bean 的生命周期由以下接口控制: ```java // 示例代码:Bean生命周期关键接口 public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName); Object postProcessAfterInitialization(Object bean, String beanName); } ``` 1. **实例化**:通过反射调用构造函数。 2. **属性注入**:通过 `populateBean()` 方法注入依赖(如 `@Autowired`)。 3. **初始化**: - 调用 `InitializingBean.afterPropertiesSet()`。 - 执行自定义初始化方法(如 `@PostConstruct`)。 4. **销毁**:容器关闭时调用 `DisposableBean.destroy()` 或自定义销毁方法。 --- #### 三、核心接口对比:BeanFactory vs ApplicationContext | 特性 | BeanFactory | ApplicationContext | |---------------------|---------------------------|----------------------------------------| | Bean实例化 | 延迟加载 | 支持预加载(通过 `refresh()` 触发) | | 国际化支持 | 无 | 有(`MessageSource`) | | 事件发布 | 无 | 有(`ApplicationEventPublisher`) | | AOP集成 | 需手动配置 | 自动集成 | | 资源访问 | 基础支持 | 扩展支持(如 `ResourceLoader`) | ApplicationContext 通过组合模式扩展了 BeanFactory 的功能[^1]。 --- #### 四、设计模式应用 1. **工厂模式**:`BeanFactory` 是工厂接口,`DefaultListableBeanFactory` 是具体实现。 2. **观察者模式**:事件广播器 (`ApplicationEventMulticaster`) 监听器 (`ApplicationListener`) 实现解耦[^3]。 3. **模板方法模式**:`AbstractApplicationContext.refresh()` 定义了容器刷新的步骤骨架。 --- #### 五、循环依赖解决 Spring 通过**三级缓存**解决循环依赖: 1. **一级缓存** (`singletonObjects`):存放完全初始化的 Bean。 2. **级缓存** (`earlySingletonObjects`):存放未完成属性注入的早期 Bean 引用。 3. **三级缓存** (`singletonFactories`):存放 Bean 工厂对象,用于生成早期代理对象。 源码关键方法: ```java // DefaultSingletonBeanRegistry 类 protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值