##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类:
public
class Properties extends Hashtable<Object,Object> {
public synchronized Object setProperty(String key, String value) {
return put(key, value);
}
public String getProperty(String key) {
Object oval = super.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
}
由此段代码可以看出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<String>());
}
###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);
}