本例以spring中的 ClassPathXmlApplicationContext 为例 :
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
synchronized (this.startupShutdownMonitor) {
// 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);
......
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//Tell the subclass to refresh the internal bean factory.
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
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(beanFactory); 这个方法就是读取xml的关键:这个方法的实现方法在ClassPathXmlApplicationContext 的直接基类 AbstractXmlApplicationContext 中。
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
......
......
loadBeanDefinitions(beanDefinitionReader);
经过一些列的loadBeanDefinitions 最终实现在XmlBeanDefinitionReader的loadBeanDefinitions()
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.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(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();
}
}
}
咱们的xml文件的形式由Resource -》encodedResource,InputSource 最终调用 doLoadBeanDefinitions(encodedResource,InputSource)方法
把咱们的Resource 转化为 Document 。 至此spring 将一个外部xml文件转化为一个内部的document对象 ,详细解析步骤下次再研究。
1.介绍一下ClassPathXmlApplicationContext : 从名字上就能看出这个applicationContext 是按照类路径读取文件的容器。如果想知道applicationContext 和 beanFactory 的区别请baidu,
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("LetsGo-servlet.xml"); 通过重载最后会调用下面的构造方法:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
这个方法是这个容器的初始化方法:spring内的容器初始化都依靠refresh()
下面介绍一下refresh()方法 这个方法存在于AbstractApplicationContext 这个基类中
synchronized (this.startupShutdownMonitor) {
// 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);
......
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//Tell the subclass to refresh the internal bean factory.
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
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(beanFactory); 这个方法就是读取xml的关键:这个方法的实现方法在ClassPathXmlApplicationContext 的直接基类 AbstractXmlApplicationContext 中。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
......
......
loadBeanDefinitions(beanDefinitionReader);
}
经过一些列的loadBeanDefinitions 最终实现在XmlBeanDefinitionReader的loadBeanDefinitions()
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.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(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();
}
}
}
咱们的xml文件的形式由Resource -》encodedResource,InputSource 最终调用 doLoadBeanDefinitions(encodedResource,InputSource)方法
把咱们的Resource 转化为 Document 。 至此spring 将一个外部xml文件转化为一个内部的document对象 ,详细解析步骤下次再研究。
本文深入剖析了Spring框架中ClassPathXmlApplicationContext如何加载并解析XML配置文件的过程,从构造方法到refresh过程,再到最终的bean定义加载。
4992

被折叠的 条评论
为什么被折叠?



