##1. ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) { //null super(parent); setConfigLocations(configLocations); //默认true if (refresh) { refresh(); }复制代码
###1.1 super()一路向上调用,直到AbstractApplicationContext
public AbstractApplicationContext(ApplicationContext parent) { this(); this.setParent(parent); }复制代码
public AbstractApplicationContext() { this.logger = LogFactory.getLog(this.getClass()); this.id = ObjectUtils.identityToString(this); this.displayName = ObjectUtils.identityToString(this); this.beanFactoryPostProcessors = new ArrayList(); this.active = new AtomicBoolean(); this.closed = new AtomicBoolean(); this.startupShutdownMonitor = new Object(); this.applicationListeners = new LinkedHashSet(); this.resourcePatternResolver = this.getResourcePatternResolver(); }复制代码
protected ResourcePatternResolver getResourcePatternResolver() { //路径解析 return new PathMatchingResourcePatternResolver(this); }复制代码
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) { Assert.notNull(resourceLoader, "ResourceLoader must not be null"); this.resourceLoader = resourceLoader; }复制代码
PathMatchingResourcePatternResolver支持Ant风格的路径解析。 ###1.2 设置配置文件路径:ClassPathXmlApplicationContext.setConfigLocations(configLocations) AbstractRefreshableConfigApplicationContext.setConfigLocations
public void setConfigLocations(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) { //将占位符(placeholder)解析成实际的地址 this.configLocations[i] = this.resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }复制代码
AbstractRefreshableConfigApplicationContext.resolvePath()
protected String resolvePath(String path) { return this.getEnvironment().resolveRequiredPlaceholders(path); }复制代码
####1.2.1 Environment接口 上一步resolvePath(String path)中用到了getEnvironment().resolveRequiredPlaceholders(path),Environment接口主要包含了针对Property的一些操作:
- 首先getEnvironment()获取Environment:如果Environment为null则new一个StandardEnvironment出来: AbstractApplicationContext.createEnvironment()
protected ConfigurableEnvironment createEnvironment() { return new StandardEnvironment(); }复制代码
而StandardEnvironment继承于AbstractEnvironment,AbstractEnvironment中包含MutablePropertySources属性:
public abstract class AbstractEnvironment implements ConfigurableEnvironment { private final MutablePropertySources propertySources = new MutablePropertySources(this.logger); //PropertyResolver : Environment的顶层接口,主要提供属性检索和解析带占位符的文本。 private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(this.propertySources); public AbstractEnvironment() { //这个抽象方法在StandardEnvironment中实现 customizePropertySources(this.propertySources); if (this.logger.isDebugEnabled()) { this.logger.debug(format( "Initialized %s with PropertySources %s", getClass().getSimpleName(), this.propertySources)); } } }复制代码
StandardEnvironment中实现抽象方法:
@Override protected void customizePropertySources(MutablePropertySources propertySources) { propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties())); propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment())); }复制代码
getSystemProperties():
try { return (Map) System.getProperties(); }catch (AccessControlException ex) { ...}复制代码
###1.2.2 Properties接口 System.getProperties():
private static Properties props;public static Properties getProperties() { //首先经过安全管理器的检查 SecurityManager sm = getSecurityManager(); if (sm != null) { sm.checkPropertiesAccess(); } return props; }复制代码
Properties类:
publicclass Properties extends Hashtable
由此段代码可以看出Properties继承于Hashtable,以键值对的方式实现。
- 回到上面的路径解析问题: this.getEnvironment().resolveRequiredPlaceholders(path)就是启动了AbstractEnvironment.resolveRequiredPlaceholders:
@Override public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException { return this.propertyResolver.resolveRequiredPlaceholders(text); }复制代码
进而启动AbstractEnvironment.propertyResolver.resolveRequiredPlaceholders(text),而AbstractEnvironment.propertyResolver:
private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(this.propertySources);复制代码
PropertySourcesPropertyResolver继承于AbstractPropertyResolver,则最终触发AbstractPropertyResolver.resolveRequiredPlaceholders(String text):
@Override public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException { //初始化占位符解析器 if (this.strictHelper == null) { this.strictHelper = createPlaceholderHelper(false); } //调用doResolvePlaceholders,进行替换占位符具体值 return doResolvePlaceholders(text, this.strictHelper); }复制代码
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) { //替换占位符具体值 return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() { @Override public String resolvePlaceholder(String placeholderName) { //通过key获取占位符对应的String类型具体值 return getPropertyAsRawString(placeholderName); } }); }复制代码
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) { Assert.notNull(value, "'value' must not be null"); //替换占位符逻辑 return parseStringValue(value, placeholderResolver, new HashSet()); }复制代码
###1.3 refresh AbstractApplicationContext中的refresh()方法是spring初始化中的核心方法,在创建IoC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在refresh之后使用的是新建立起来的IoC容器。 AbstractApplicationContext.refresh():
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 设置启动时间,是否激活标识位,初始化属性源(property source)配置 prepareRefresh(); // 创建beanFactory(过程是根据xml为每个bean生成BeanDefinition并注册到生成的beanFactory) 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); // 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) { 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(); } } }复制代码
####加载类 obtainFreshBeanFactory()方法实现了类的装载,AbstractApplicationContext的obtainFreshBeanFactory()方法调用子类AbstractRefreshableApplicationContext的refreshBeanFactory()方法,启动容器载入Bean定义资源文件的过程: AbstractApplicationContext.obtainFreshBeanFactory():
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }复制代码
AbstractRefreshableApplicationContext.refreshBeanFactory():
@Override protected final void refreshBeanFactory() throws BeansException { //从这里可以看出,如果存在容器则销毁并关闭 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //new出一个新的DefaultListableBeanFactory作为IoC容器 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); //对IoC容器进行定制化,如设置启动参数,开启注解的自动装配等 customizeBeanFactory(beanFactory); //调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器(AbstractXmlApplicationContext) loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }复制代码
AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory):
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. 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); }复制代码