博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring
阅读量:5914 次
发布时间:2019-06-19

本文共 10446 字,大约阅读时间需要 34 分钟。

##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
{ 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
()); }复制代码

###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);	}复制代码

转载地址:http://bcwvx.baihongyu.com/

你可能感兴趣的文章
mian方法中的String[] args,命令行运行参数的传入
查看>>
基于Linux的行为查杀的反病毒软件的一二思路
查看>>
NLTK学习笔记(二)
查看>>
Mysql无法update表的解决方案
查看>>
用况和构架的关系
查看>>
shell中$的含义
查看>>
高效开发iOS系列 -- 为Xcode添加删除行、复制行快捷键
查看>>
oracle Round() 函数
查看>>
javascript 星星评价(转)
查看>>
iTween基础之Value(数值过度)
查看>>
phpcms自动检测百度是否收录插件
查看>>
在防火墙后架设***服务器
查看>>
我的友情链接
查看>>
初学者对思科设备操作模式的疑惑
查看>>
使用prometheus_client监控程序
查看>>
Nginx 配置文件示例解析
查看>>
Android应用性能优化之使用SparseArray替代HashMap
查看>>
人生,其实需要营销
查看>>
实战微软云计算设计与实践虚拟数据中心
查看>>
我国软件产业面临的成本上升压力分析
查看>>