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

目录

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

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值