前言
在文章 ApplicationContext 体系结构 中我们从一张 ApplicationContext 体系的类图开始,介绍了 ApplicationContext 体系中各个类的继承关系,接着分析了 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 类的构造函数中前两个函数的源码。从本篇文章开始,将重点介绍 refresh 函数。
-
AbstractApplicationContext::refresh
ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 类均继承了 AbstractApplicationContext 类,refresh 方法在该类中实现。public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 刷新预处理 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // (1) 创建 IOC 容器(DefaultListableBeanFactory) // (2) 加载 xml 文件(最终生成 Document 对象) // (3) 读取 Document 对象,完成 BeanDefinition 的加载和注册 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 对IOC容器进行预处理 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 调用BeanFactoryPostProcessor后置处理器对 BeanDefinition 处理 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注册BeanPostProcessor后置处理器 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // STEP 7: 初始化一些消息源(比如处理国际化的i18n等消息源) initMessageSource(); // Initialize event multicaster for this context. // STEP 8: 初始化应用事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // STEP 9: 初始化一些特殊的bean onRefresh(); // Check for listener beans and register them. // STEP 10: 注册一些监听器 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // STEP 11: 实例化剩余的单例bean(非懒加载方式) // 注意事项:Bean的IoC、DI和AOP都是发生在此步骤 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // STEP 12: 完成刷新时,需要发布对应的事件 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(); } } }
-
AbstractApplicationContext::prepareRefresh
protected void prepareRefresh() { // Switch to active. // 记录启动时间,容器状态 this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } // Initialize any placeholder property sources in the context environment. // 空函数什么也没做,初始化属性配置在其子类中有实现(例如:AbstractRefreshableWebApplicationContext、GenericWebApplicationContext等) initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties /** * 1. 获取 ConfigurableEnvironment * 2. 确保配置所有必须的属性 **/ 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<>(); }
-
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
创建 BeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 1. refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
-
refreshBeanFactory
AbstractApplicationContext 中该方法为空,在子类 AbstractRefreshableApplicationContext(ClassPathXmlApplicationContext继承该类)、GenericApplicationContext(AnnotationConfigApplicationContext继承该类)中对该方法进行了扩展。-
AbstractRefreshableApplicationContext::refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException { // 若已存在 BeanFactory,则销毁容器中的 Bean 实例,将 BeanFactory 置为 null if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 创建 BeanFactory 实例,类型为:DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖 // 可在子类中去扩展定义属性:allowBeanDefinitionOverriding, allowCircularReferences customizeBeanFactory(beanFactory); // 加载 BeanDefinition,并注册到IoC容器中(重点) loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
- loadBeanDefinitions
在 AbstractRefreshableApplicationContext::refreshBeanFactory 中 loadBeanDefinitions 为重点代码,接下来将详细介绍改部分的代码。|-- AbstractRefreshableApplicationContext::refreshBeanFactory |-- AbstractXmlApplicationContext::loadBeanDefinitions:走了多个重载方法 |--AbstractBeanDefinitionReader::loadBeanDefinitions:走了多个重载方法 |--XmlBeanDefinitionReader::loadBeanDefinitions:走了多个重载方法 |--XmlBeanDefinitionReader::doLoadBeanDefinitions |--XmlBeanDefinitionReader::registerBeanDefinitions |-- DefaultBeanDefinitionDocumentReader ::registerBeanDefinitions ::doRegisterBeanDefinitions ::parseBeanDefinitions ::parseDefaultElement ::processBeanDefinition |--BeanDefinitionParserDelegate ::parseBeanDefinitionElement ::parseBeanDefinitionElement 1. AbstractRefreshableApplicationContext:主要用来对BeanFactory提供 refresh 功能。包括BeanFactory的创建和 BeanDefinition 的定义、解析、注册操作。 2. AbstractXmlApplicationContext:提供对 xml 资源的解析功能,包括从Resource资源对象和资源路径中加载XML文件。 3. AbstractBeanDefinitionReader:主要提供对于 BeanDefinition 对象的读取功能。具体读取工作交给子类实现。 4. XmlBeanDefinitionReader:主要通过 DOM4J 对于 XML资源 的读取、解析功能,并提供对于 BeanDefinition 的注册功能。 5. DefaultBeanDefinitionDocumentReader 6. BeanDefinitionParserDelegate
- AbstractXmlApplicationContext::loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. // 创建 XmlBeanDefinitionReader, 此时会初始化 ResourceLoaderLoader 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); } protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { // debug 中 configResourses 为 null Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { // 根据配置文件位置加载BeanDefinition reader.loadBeanDefinitions(configLocations); } } // AbstractBeanDefinitionReader::loadBeanDefinitions public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null"); int counter = 0; for (String location : locations) { counter += loadBeanDefinitions(location); } return counter; } public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException { // 初始化 XmlBeanDefinitionReader 时已经初始化了 ResourceLoader // XmlBeanDefinitionReader 无法直接加载配置文件,因此需要委托 ResourceLoader 将配置文件加载为 Resource 对象 ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available"); } if (resourceLoader instanceof ResourcePatternResolver) { // Resource pattern matching available. try { Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); // 根据 Resource 加载 BeanDefinition int loadCount = loadBeanDefinitions(resources); if (actualResources != null) { for (Resource resource : resources) { actualResources.add(resource); } } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]"); } return loadCount; } catch (IOException ex) { throw new BeanDefinitionStoreException( "Could not resolve bean definition resource pattern [" + location + "]", ex); } } else { // Can only load single resources by absolute URL. Resource resource = resourceLoader.getResource(location); int loadCount = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]"); } return loadCount; } }
- XmlBeanDefinitionReader::loadBeanDefinitions
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } // 核心代码 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } } protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { // 将配置文件转换为 Document 对象 Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); } // .. 此处异常捕获处理代码省去 } public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 创建 DefaultBeanDefinitionDocumentReader 对象 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); // 1. 创建 Reader 上下文 // 2. 根据 Document 对象加载 BeanDefinition documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
- XmlBeanDefinitionReader::registerBeanDefinitions
// 创建 XmlReaderContext, 需要创建 NameSpaceHandlerResolver 用来处理 xml 配置文件中的各命名空间 // 读取 "META-INF/spring.handlers" 创建 DefaultNamespaceHandlerResolver public XmlReaderContext createReaderContext(Resource resource) { return new XmlReaderContext(resource, this.problemReporter, this.eventListener, this.sourceExtractor, this, getNamespaceHandlerResolver()); } public NamespaceHandlerResolver getNamespaceHandlerResolver() { if (this.namespaceHandlerResolver == null) { this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver(); } return this.namespaceHandlerResolver; } protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() { ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader()); return new DefaultNamespaceHandlerResolver(cl); } public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) { //public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers"; this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); }
- DefaultBeanDefinitionDocumentReader::registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); } protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; // 根据 Reader 上下文创建 BeanDefinitionParserDelegate this.delegate = createDelegate(getReaderContext(), root, parent); /** * BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext); * delegate.initDefaults(root, parentDelegate); **/ if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } // 空函数 preProcessXml(root); // 解析标签 parseBeanDefinitions(root, this.delegate); // 空函数 postProcessXml(root); this.delegate = parent; } 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)) { // 处理默认的标签元素:bean/import/alias/beans parseDefaultElement(ele, delegate); } else { // 处理自定义的标签 delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } } 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)) { // 处理 bean 标签 processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse 递归调用 doRegisterBeanDefinitions(ele); } } protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 解析 Bean 标签,创建 BeanDefinitionHolder 对象 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } } public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); // 注册 BeanDefinition 至于 DefaultListableBeanFactory 的 beanDefinitionMap 中 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } } // 自定义命名空间的解析,如: context,aop,tx public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } // 根据 META-INF/spring.handlers 中的配置,找到 Namespace 对应的 Handler 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 实现的 parse 方法将 dom element 解析为 BeanDefinition return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
上述源码流程即为 obtainFreshBeanFactory 的过程,主要完成了
- 创建了 DefaultListableBeanFactory;
- 读取配置文件,完成了BeanDefinition的加载
引申:
在对自定义命名空间进行处理时,会有一些预置的 BeanDefinition 的加载,例如对 context:annotation-config 标签处理时,会加载 ConfigurationClassPostProcessor 类(BeanFactoryPostProcessor)的 BeanDefinition, 在后续 invokeBeanFactoryPostProcessors 方法中,会使用到该扩展点public class ContextNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); // 对 @autowired、@ Resource 、@ PostConstruct、@ PreDestroy、@Required、@PersistenceContext 注解解析 registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); // 除了annotation-config对应的注解解析外,扩展了 @Component 注解的支持,因此如果配制了 context:component-scan 就无须再配置 context:annotation-config 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()); } }
- loadBeanDefinitions
-
GenericApplicationContext::refreshBeanFactory
GenericApplicationContext 的 refresh 方法相比于 AbstractRefreshableApplicationContext 要简单许多,只有一个 refresh 标记的判断以及序列化 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()); }
-
-
总结
本篇文章中首先对 refresh 函数源码进行了简单的分析,了解了各个函数大概的作用,然后针对 prepareRefresh 和 obtainFreshBeanFactory 函数做了详细的分析。
- prepareRefresh
在该函数中进行了一些容器刷新的准备,如记录容器启动时间、定义早期事件的监听器等 - obtainFreshBeanFactory
AbstractApplicationContext 中该方法为空,在其子类 AbstractRefreshableApplicationContext 和 GenericApplicationContext 中对该方法进行了扩展。- AbstractRefreshableApplicationContext
方法中首先定义了 beanDefinitionReader,然后读取配置文件将配置文件中定义的 Bean 信息加载为 BeanDefinition,需要注意的是其中包含一些自定义命名空间的解析。 - GenericApplicationContext
仅做了refresh 标记的判断以及序列化 ID 的设置
- AbstractRefreshableApplicationContext
网友评论