spring 源码解读二 AbstractApplicationContext refresh

今天我们重点来看下 AbstractApplicationContext 的 refresh()方法,上次说了这个方法算是spring最核项的方法了大概可以归为 13个方法

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.

			/**
			 * 1、
			 * 创建spring 容器之前的准备工作
			 * 包括设置启动时间、活跃状态、加载当前环境变量、准备监听器集合
			 */
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			/**
			 * 2、
			 * 创建BeanFactory容器对象:实际对象为 DefaultListableBeanFactory
			 * 加载xml配置文件到当前工厂中
			 */
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			/**
			 * 3、
			 * 初始化BeanFactory
			 * 设置各种系统对象的初始值
			 */
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 4、子类可扩展方法,留给用户扩展
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				/**
				 * 5、
				 * 调用各种BeanFactoryPostProcessor处理器与BeanDefinitionRegistryPostProcessor 处理器
				 * 可参考 ConfigurationClassPostProcessor  -- 解析各种注解配置的bean
				 * 包括 @Configuration
				 * 		@Component
				 * 		@ComponentScan
				 * 		@PropertySource-这里是将配置文件加载到环境变量里面
				 * 		@Bean
				 * 		@Import
				 * 可参考 PropertySourcesPlaceholderConfigurer -- 解析配置文件中的${name}这种变量
				 */
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				/**
				 * 6、
				 * 注册BeanPostProcessor处理器
				 * 可参考 ApplicationContextAwareProcessor  -- 执行除了 BeanNameAware BeanClassLoaderAware BeanFactorAware 之外的其他aware
				 * 可参考 ApplicationListenerDetector -- 监听器的探测器
				 *
				 * 这里要注意的是
				 * 		@CommonAnnotationBeanPostProcessor --处理@Resource等注解
				 * 		@InitDestroyAnnotationBeanPostProcessor --处理 @PostConstruct 注解与 @PreDestroy
				 * 		@AutowiredAnnotationBeanPostProcessor --处理 @Autowire 注解与 @Value 注解
				 *  这几个类也是 BeanPostProcessor 的实现类,这几个类我们将在后面的bean初始化的时候重点研究
				 */
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 7、不同语言的消息体,国际化处理
				initMessageSource();

				// Initialize event multicaster for this context.
				// 8、初始化事件广播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 9、子类可扩展方法,留给用户扩展
				onRefresh();

				// Check for listener beans and register them.
				// 10、在BeanFactory 中查找listener bean,注册到事件广播器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 11、初始化用户定义的还未被实例化的单例bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 12、完成spring容器的初始化与刷新,设置生命周期处理器,发布ContextRefreshEvent 事件
				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...
				// 13、清理在BeanFactory创建过程中以及用户bean实例化初始化过程中产生的缓存
				resetCommonCaches();
			}
		}
	}

后面会逐个解析标注的 13个方法

首先是 prepareRefresh() 

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());
			}
		}

		// Initialize any placeholder property sources in the context environment.
        //用户扩展方法
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#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<>();
	}

obtainFreshBeanFactory() 

/**
	 * Tell the subclass to refresh the internal bean factory.
	 * @return the fresh BeanFactory instance
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //初始化一个BeanFactory
		refreshBeanFactory();
		return getBeanFactory();
	}

refreshBeanFactory() -> AbstractRefreshableApplicationContext

@Override
	protected final void refreshBeanFactory() throws BeansException {
        //如果之前已经存在BeanFactory则销毁之前的beanFactory中的bean并关闭beanFactory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
            //新建一个 DefaultListableBeanFactory 
			DefaultListableBeanFactory beanFactory = createBeanFactory();

            //给beanFactory设置一个id值
			beanFactory.setSerializationId(getId());
            
            //这里可以设置bean定义信息是否允许被覆盖和是否允许循环引用
			customizeBeanFactory(beanFactory);

            //加载 myApplicationContext.xml 配置文件并解析里面的bean内容为beanDefinition
			loadBeanDefinitions(beanFactory);

			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
 createBeanFactory()
protected DefaultListableBeanFactory createBeanFactory() {
		return new DefaultListableBeanFactory(getInternalParentBeanFactory());
	}

new DefaultListableBeanFactory(getInternalParentBeanFactory()) 

public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		super(parentBeanFactory);
	}
super(parentBeanFactory) -> AbstractAutowireCapableBeanFactory
public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		this();
		setParentBeanFactory(parentBeanFactory);
	}
public AbstractAutowireCapableBeanFactory() {
		super();
		//这里有三个aware接口被忽略,记住这里
		ignoreDependencyInterface(BeanNameAware.class);
		ignoreDependencyInterface(BeanFactoryAware.class);
		ignoreDependencyInterface(BeanClassLoaderAware.class);
	}
AbstractRefreshableApplicationContext -> customizeBeanFactory(beanFactory)
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
		// 是否允许对象覆盖
		if (this.allowBeanDefinitionOverriding != null) {
			beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		// 是否允许bean之间的循环引用
		if (this.allowCircularReferences != null) {
			beanFactory.setAllowCircularReferences(this.allowCircularReferences);
		}
	}
AbstractRefreshableApplicationContext -> loadBeanDefinitions(beanFactory) 这里面的内容太特么绕了多了我用图表示一下吧

 

 

经过上面一系列的过程只是把我们定义在 myApplicationContext.xml 的默认标签给解析了

DefaultBeanDefinitionDocumentReader -> parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
                        //这里解析默认命名空间的标签包括 import、bean、beans、alias
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
            //这里解析其他命名空间的标签比如 context、aop、tx或我们自定义的标签
			delegate.parseCustomElement(root);
		}
	}

DefaultBeanDefinitionDocumentReader -> parseDefaultElement(ele, delegate);

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

DefaultBeanDefinitionDocumentReader -> delegate.parseCustomElement(root);

@Nullable
	public BeanDefinition parseCustomElement(Element ele) {
		return parseCustomElement(ele, null);
	}

DefaultBeanDefinitionDocumentReader -> parseCustomElement(ele, null);

@Nullable
	public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		// 根据我们 myApplicationContext.xml 中定义的标签引入文件
        // 比如 http://www.springframework.org/schema/context
        // 根据 http://www.springframework.org/schema/context到resource下的 META-INF 下的
        // spring.handlers中找到对应的 NamespaceHandler
        // 获取对应NamespaceHandler 下的标签解析类来解析对应标签
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		// 根据命名空间找到对应的NamespaceHandlerspring
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		// 调用自定义的NamespaceHandler进行解析
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

这里以context标签为例进行说明 我在myApplicationContext.xml 中已经做了如下定义

<context:component-scan base-package="com.demo.person"></context:component-scan>

spring-context -> src->main->resources -> META-INF-> spring.handlers

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

因此context标签会直接定位到 org.springframework.context.config.ContextNamespaceHandler

public class ContextNamespaceHandler extends NamespaceHandlerSupport {

	@Override
	public void init() {
		registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
		registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
		registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
		registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
	}

}

因为我们定义了 component-scan标签因此会调用 new ComponentScanBeanDefinitionParser() 的parse方法

注意这里不是说在配置文件里面写了component-scan 就调 new ComponentScanBeanDefinitionParser() 的parse方法,而是init下的所有类的parse方法都会执行

好了我们回到DefaultBeanDefinitionDocumentReader -> parseCustomElement(ele, null) -> handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))

NamespaceHandlerSupport -> BeanDefinition parse(Element element, ParserContext parserContext)

@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		// 获取元素的解析器
		BeanDefinitionParser parser = findParserForElement(element, parserContext);
        // 根据 registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); 
//找到 ComponentScanBeanDefinitionParser() 解析器并调用ComponentScanBeanDefinitionParser()的parse方法解析标签
		return (parser != null ? parser.parse(element, parserContext) : null);
	}

好了 AbstractApplicationContext -> refresh -> obtainFreshBeanFactory  基本看完了操

请大家关注下博客谢谢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值