Spring源码解析-refresh()-prepareRefresh方法

往后我们进入到refresh方法内部进去处理

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			//准备此上下文以进行刷新
			prepareRefresh(); 
            // Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

总结:  这个类的主要工作是前戏

  1. 设置容器的启动时间

  2. 设置关闭状态为false

  3. 设置活跃状态为false

  4.获取getEnvironment()对象,并加载系统的属性值到enviorment到对象中

  5.准备监听器和事件的集合对象,默认为空的对象。 

准备此上下文以进行刷新、设置其启动日期和活动标志以及执行属性源的任何初始化。
protected void prepareRefresh() {
		// 启动时间
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);
        // 打印日志 没啥说的
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		//在上下文环境中初始化任何占位符属性源。注:这个是空的方法,其是由子类进行实现的。
		initPropertySources();
  
		// 验证所有标记为必需的属性都是可解析的
		//参见 ConfigurablePropertyResolvetRequiredProperties
        //注: 此时环境参数初始好了的, 在setConfigLocations 中进行了配置 详细见上一篇https://blog.csdn.net/u012249177/article/details/120006362
		getEnvironment().validateRequiredProperties();

		// 存储预刷新 ApplicationListener
		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<>();
	}

 细节点一: initPropertySources  空方法由子类实现, 添加一个参数和一些校验等

  如新建类MyClassPathXmlApplicationContext 继承了ClassPathXmlApplicationContext 重写了改方法:

 

getEnvironment().validateRequiredProperties(): 验证所有标记为必需的属性都是可解析的

如果initPropertySources  中 写上:

 @Override
    protected void initPropertySources() {
        System.out.println("扩展initPropertySource");
        getEnvironment().setRequiredProperties("abc"); //设置了需要的参数 username, 那么在后续就会校验这个参数舒存在
    }

后面处理流程:

@Override
	public void validateRequiredProperties() {
		MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
		for (String key : this.requiredProperties) {
			if (this.getProperty(key) == null) { // 从配置参数中获取value ,如果没有key则进行报错
			ex.addMissingRequiredProperty(key);
			}
		}
		if (!ex.getMissingRequiredProperties().isEmpty()) {
			throw ex;
		}
	}

因为此时环境参数中并没有abc这个参数,然后就会报:

Exception in thread "main" org.springframework.core.env.MissingRequiredPropertiesException: The following properties were declared as required but could not be resolved: [abc]
	at org.springframework.core.env.AbstractPropertyResolver.validateRequiredProperties(AbstractPropertyResolver.java:145)

附:代码:

package com.mashibing;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.Assert;

public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {


    public MyClassPathXmlApplicationContext(String... configLocations){
        super(configLocations);
    }

    @Override
    protected void initPropertySources() {
        System.out.println("扩展initPropertySource");
        getEnvironment().setRequiredProperties("username"); //设置了需要的参数 username, 那么在后续就会校验这个参数舒存在
    }

    @Override
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//        super.setAllowBeanDefinitionOverriding(false);
//        super.setAllowCircularReferences(false);
        super.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
        super.customizeBeanFactory(beanFactory);
    }

    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        System.out.println("扩展实现postProcessBeanFactory方法");
    }
}

                                                                                                          


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
`refresh()` 是 Spring 框架中的一个方法,它用于刷新应用程序上下文(ApplicationContext)以更新其内部状态。在 Spring 框架中,`refresh()` 方法是非常重要的,因为它负责完成应用程序上下文的初始化和配置,并准备好所有的单例 bean 以供使用。 下面是 `refresh()` 方法的主要流程: 1. 准备刷新过程中需要用到的变量和标志位; 2. 调用 `prepareRefresh()` 方法,进行一些预处理工作; 3. 调用 `obtainFreshBeanFactory()` 方法,创建 BeanFactory 并进行一些初始化工作; 4. 调用 `prepareBeanFactory(beanFactory)` 方法,对 BeanFactory 进行一些后续处理; 5. 调用 `postProcessBeanFactory(beanFactory)` 方法,对 BeanFactory 进行后置处理; 6. 调用 `invokeBeanFactoryPostProcessors(beanFactory)` 方法,执行 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法; 7. 调用 `registerBeanPostProcessors(beanFactory)` 方法,注册 BeanPostProcessor 实例; 8. 调用 `initMessageSource()` 方法,初始化 MessageSource 组件; 9. 调用 `initApplicationEventMulticaster()` 方法,初始化 ApplicationEventMulticaster 组件; 10. 调用 `onRefresh()` 方法,进行一些自定义的刷新工作; 11. 调用 `registerListeners()` 方法,注册事件监听器; 12. 调用 `finishBeanFactoryInitialization(beanFactory)` 方法,完成所有非延迟初始化的单例 bean 的初始化工作; 13. 调用 `finishRefresh()` 方法,完成上下文的刷新工作。 需要注意的是,`refresh()` 方法在执行过程中会涉及到很多细节,比如如何处理环境变量、如何处理自定义的 bean 定义、如何处理多个上下文之间的关系等等。如果需要深入了解 `refresh()` 方法的实现细节,可以查看 Spring 框架的源代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值