啥十小企业网站建设/优化分析
一、引言
上一篇Spring 源码分析(二)— IOC 根类结构图梳理了整个 Spring BeanFactory 的继承关系,对 BeanFactory 家族有了一个基本的认知。
本篇继续接着Spring 源码分析(一)— IOC demo ,来分析 ClassPathXmlApplicationContext 的初始化过程。
二、初始化过程分析
ClassPathXmlApplicationContext 过程跟踪:
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {....../*** Create a new ClassPathXmlApplicationContext, loading the definitions* from the given XML file and automatically refreshing the context.* @param configLocation resource location* @throws BeansException if context creation failed*/public ClassPathXmlApplicationContext(String configLocation) throws BeansException {this(new String[] {configLocation}, true, null);}....../*** Create a new ClassPathXmlApplicationContext with the given parent,* loading the definitions from the given XML files.* @param configLocations array of resource locations* @param refresh whether to automatically refresh the context,* loading all bean definitions and creating all singletons.* Alternatively, call refresh manually after further configuring the context.* @param parent the parent context* @throws BeansException if context creation failed* @see #refresh()*/public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)throws BeansException {super(parent);setConfigLocations(configLocations);if (refresh) {refresh();}}......
可知:
初始化入口是 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) 方法;
该方法做了三件事:
- super(parent); 设置 ApplicationContext;
- setConfigLocations(configLocations); 设置配置文件路径;
- refresh(); 加载新配置;
1.super(parent); 设置 ApplicationContext;真正执行的是 AbstractApplicationContext 类的方法:
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {....../*** Create a new AbstractApplicationContext with no parent.*/public AbstractApplicationContext() {this.resourcePatternResolver = getResourcePatternResolver();}/*** Create a new AbstractApplicationContext with the given parent context.* @param parent the parent context*/public AbstractApplicationContext(@Nullable ApplicationContext parent) {this();setParent(parent);}....../*** Set the parent of this application context.* <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is* {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with* this (child) application context environment if the parent is non-{@code null} and* its environment is an instance of {@link ConfigurableEnvironment}.* @see ConfigurableEnvironment#merge(ConfigurableEnvironment)*/@Overridepublic void setParent(@Nullable ApplicationContext parent) {this.parent = parent;if (parent != null) {Environment parentEnvironment = parent.getEnvironment();if (parentEnvironment instanceof ConfigurableEnvironment configurableEnvironment) {getEnvironment().merge(configurableEnvironment);}}}......
2.setConfigLocations(configLocations); 设置配置文件路径;真正执行的是 AbstractRefreshableConfigApplicationContext 的 public void setConfigLocations(@Nullable String… locations) 方法:
public abstract class AbstractRefreshableConfigApplicationContext extends AbstractRefreshableApplicationContextimplements BeanNameAware, InitializingBean {....../*** Set the config locations for this application context.* <p>If not set, the implementation may use a default as appropriate.*/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;}}......
3.refresh(); 加载新配置;真正执行的是 AbstractApplicationContext 的 refresh(…) 方法:
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext {......@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);beanPostProcess.end();// 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();contextRefresh.end();}}}......