Spring-AbstractApplicationContext

@Override
public void refresh() throws BeansException, IllegalStateException {
    
    
	synchronized (this.startupShutdownMonitor) {
    
    
		// 该方法请查看文章下面的"一:prepareRefresh()方法"
		prepareRefresh();

		// new一个DefaultListableBeanFactory,它同时也是一个BeanDefinitionRegistry,
		//然后使用ClassPathBeanDefinitionScanner和AnnotatedBeanDefinitionReader扫描,最后生成BeanDefinition
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 本方法最重要的地方就是处理Aware接口的实现类(ApplicationContextContextAware)
		// 其他地方对学习和研究源码意义不大,但是对spring初始过程很重要
		// 没必要纠结这些方法,因为我已经踩过坑了,意义不大
		// 添加SPEL语言的解析器
		// 添加属性编辑器
		// 忽略一些自动装配的接口(此处属于难点,需要你了解xml中的default-autowire,然而现在没多少人使用xml格式了),而@Autowired并不是我们说的自动装配
		// 增加对AspectJ的支持
		// 设置环境变量
		prepareBeanFactory(beanFactory);

		try {
    
    
			// Allows post-processing of the bean factory in context subclasses.
			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();
		}
	}
}

一:prepareRefresh()方法
此方法最大的作用:当我们自己实现容器的时候,用来校验系统变量是否正确
当我们自己实现容器的时候,如果重写了initPropertySources();方法,那么就会体现出prepareRefresh方法的作用

	/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 */
	protected void prepareRefresh() {
    
    
		// Switch to active.
		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();
		// 配合上边这个init方法执行校验
		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<>();
	}

示例需求:程序启动之后,必须要用到一个系统变量abc,如果没有abc这个变量,程序将无法正确执行,所以程序启动之前,必须校验是否存在变量abc

示例代码:

public class MysTest extends ClassPathXmlApplicationContext {
    
    

	@Override
	protected void initPropertySources() {
    
    
		// 不只是setRequiredProperties方法,还有很多方法用来实现更多的特性
		getEnvironment().setRequiredProperties("abc");
	}

	public static void main(String[] args) {
    
    
		ClassPathXmlApplicationContext ctx = new MysTest();
		// 下面这个方法会报错,提示没有abc,报错信息如下
		// The following properties were declared as required 
		// but could not be resolved: [abc]
		ctx.refresh();
	}
}

猜你喜欢

转载自blog.csdn.net/u011624903/article/details/112216469