从ClassPathXmlApplicationContext中看spring在web中如何运行

来源:互联网 发布:iscroll.js 下载 编辑:程序博客网 时间:2024/06/04 00:51


十一小长假在家玩和太happy了。根本没有时间看java之类的东西,今天是假日最后一天,所以会把上次的补上

个人感觉在web中看spring如何解析如何运行是一件比较难的事,spring附加了在我们看来是没有用的代码,但是既然它写了肯定是有用处的,这是我们初级程序员可以学习的地方。好了不多说了。看代码

ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
我们来看看ClassPathXmlApplicationContext的构造器

public ClassPathXmlApplicationContext(String configLocation)/*     */     throws BeansException/*     */   {/*  83 */     this(new String[] { configLocation }, true, null);/*     */   }

为什么我的反编译有行数的。。你问我。。我也不知道。。。。

this是当前类继续看

   public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)/*     */     throws BeansException/*     */   {/* 136 */     super(parent);/* 137 */     setConfigLocations(configLocations);/* 138 */     if (refresh)/* 139 */       refresh();/*     */   }
先看下super。。。super调用的是父类构造器

看下AbstractXmlApplicationContext

  public AbstractXmlApplicationContext(ApplicationContext parent)/*     */   {/*  58 */     super(parent);/*     */   }
还是一样。。继续看

看下AbstractRefreshableConfigApplicationContext

public AbstractRefreshableConfigApplicationContext(ApplicationContext parent)  {    super(parent);  }

还是一样。继续看下AbstractRefreshableApplicationContext

 public AbstractRefreshableApplicationContext(ApplicationContext parent)  {    super(parent);  }


看下AbstractApplicationContext

 public AbstractApplicationContext(ApplicationContext parent)  {    this.logger = LogFactory.getLog(getClass());    this.id = ObjectUtils.identityToString(this);    this.beanFactoryPostProcessors = new ArrayList();    this.active = false;    this.activeMonitor = new Object();    this.startupShutdownMonitor = new Object();    this.applicationListeners = new ArrayList();    this.parent = parent;    this.resourcePatternResolver = getResourcePatternResolver();  }

上面没有什么好看的。无非是初始化我们看下最后this.resourcePatternResolver = getResourcePatternResolver();

protected ResourcePatternResolver getResourcePatternResolver()  {    return new PathMatchingResourcePatternResolver(this);  }

这是我自己写的PathMatchingResourcePatternResolver

public static void main(String[] args){ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();              Resource[] resources = null;try {resources = resolver.getResources("file:"+System.getProperty("user.dir")+"/WebRoot/WEB-INF/spring01/*/*.xml");System.out.println(resources[0].getURL()); System.out.println(resources.length);} catch (IOException e) {e.printStackTrace();}   }


这个类是干嘛的就是匹配*的,所以我们配spring.xml不用一个一个去配了。直接用这类,就行了。。

AbstractApplicationContext中主要是初始化。看不看意义不大,关键看下这个

 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)    throws BeansException  {    super(parent);    setConfigLocations(configLocations);    if (refresh)      refresh();  }

setConfigLocations(configLocations);这个不用说了吧。。。更简单了,把spring.xml的名字放进来嘛

看下if (refresh)

 refresh();

其实refresh肯定为true,这个我们应该能感觉到,事实也是这样

 public ClassPathXmlApplicationContext(String configLocation)    throws BeansException  {    this(new String[] { configLocation }, true, null);  }

直接把true传过来了

关键是看下refresh()这个方法。。我们来看下。。。。refresh()这个方法是在AbstractApplicationContext这个类中,spring的目的是解耦合,但是他自己写的确实耦合度不是一般的高

 public void refresh() throws BeansException, IllegalStateException  {    synchronized (this.startupShutdownMonitor)    {      prepareRefresh();      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();      prepareBeanFactory(beanFactory);      try      {        postProcessBeanFactory(beanFactory);        invokeBeanFactoryPostProcessors(beanFactory);        registerBeanPostProcessors(beanFactory);        initMessageSource();        initApplicationEventMulticaster();        onRefresh();        registerListeners();        finishBeanFactoryInitialization(beanFactory);        finishRefresh();      }      catch (BeansException ex)      {        beanFactory.destroySingletons();        cancelRefresh(ex);        throw ex;      }    }  }

synchronized (this.startupShutdownMonitor) {

 prepareRefresh();
这个我们这里就不看了。无非是同步一些东西,看也看不懂,继续


 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

我们看下obtainFreshBeanFactory这个方法

protected ConfigurableListableBeanFactory obtainFreshBeanFactory()  {    refreshBeanFactory();    ConfigurableListableBeanFactory beanFactory = getBeanFactory();    if (this.logger.isInfoEnabled()) {      this.logger.info("Bean factory for application context [" + getId() + "]: " + ObjectUtils.identityToString(beanFactory));    }    if (this.logger.isDebugEnabled()) {      this.logger.debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this);    }    return beanFactory;  }


看下refreshBeanFactory()这个方法

 protected abstract void refreshBeanFactory()    throws BeansException, IllegalStateException;

在他自己类中是这样写的。我们是看父类代码还是看子类代码呢。。。肯定是看子类的代码吗。abstract在,,那不用看了。。去他的子类找一找

在AbstractRefreshableApplicationContext中找到了refreshBeanFactory()的实现

 protected final void refreshBeanFactory()    throws BeansException  {    if (hasBeanFactory()) {      destroyBeans();      closeBeanFactory();    }    try {      DefaultListableBeanFactory beanFactory = createBeanFactory();      customizeBeanFactory(beanFactory);      loadBeanDefinitions(beanFactory);      synchronized (this.beanFactoryMonitor) {        this.beanFactory = beanFactory;      }    }    catch (IOException ex) {      throw new ApplicationContextException("I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);    }  }


我们看下第一个if()中写的是hasBeanFactory()英文意思写得非常明白是滞有bean工厂吗,有的话销毁beans还有关闭bean工厂吗。如果你是第一次初始化就直接看下try-catch里面代码好了

DefaultListableBeanFactory beanFactory = createBeanFactory();

这个是实例化beanFactory其实我们不用看的。浪费时间。。。。

继续

customizeBeanFactory(beanFactory);定制客户的专属bean工厂也不用看的

关键的来了

loadBeanDefinitions(beanFactory);我们看下原码

在它的本类中

protected abstract void loadBeanDefinitions(DefaultListableBeanFactory paramDefaultListableBeanFactory)    throws IOException, BeansException;


写的又是这样一句话。。。。看子类嘛。。。。其实第一次看真的会晕

在AbstractXmlApplicationContext这个类中实现了loadBeanDefinitions的方法。看下

 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)    throws IOException  {    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);    beanDefinitionReader.setResourceLoader(this);    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));    initBeanDefinitionReader(beanDefinitionReader);    loadBeanDefinitions(beanDefinitionReader);  }

我们看最关键的

loadBeanDefinitions(beanDefinitionReader);

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)    throws BeansException, IOException  {    Resource[] configResources = getConfigResources();    if (configResources != null)      reader.loadBeanDefinitions(configResources);    String[] configLocations = getConfigLocations();    if (configLocations != null)      reader.loadBeanDefinitions(configLocations);  }

getConfigResources();

protected Resource[] getConfigResources()  {    return null;  }

你说看了有什么用。。。直接不用看

String[] configLocations = getConfigLocations();

我们刚刚在refresh()上面是不是setConfigLocations()了;

那这里我们不就是直接获得了嘛,简单

if (configLocations != null)

reader.loadBeanDefinitions(configLocations);

这里configLocations肯定不为空啊。

看下

public int loadBeanDefinitions(String[] locations) throws BeanDefinitionStoreException  {    Assert.notNull(locations, "Location array must not be null");    int counter = 0;    for (int i = 0; i < locations.length; ++i)      <pre class="html" name="code">counter += loadBeanDefinitions(locations[i]);    return counter;  }

看下

counter += loadBeanDefinitions(locations[i]);

我就直接copy出来了

public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {    return loadBeanDefinitions(location, null);  }  public int loadBeanDefinitions(String location, Set actualResources)    throws BeanDefinitionStoreException  {    ResourceLoader resourceLoader = getResourceLoader();    if (resourceLoader == null) {      throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");    }    if (resourceLoader instanceof ResourcePatternResolver) {      try      {        Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);        loadCount = loadBeanDefinitions(resources);        if (actualResources != null)          for (int i = 0; i < resources.length; ++i)            actualResources.add(resources[i]);        if (this.logger.isDebugEnabled())          this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");        return loadCount;      }      catch (IOException ex) {        throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", ex);      }    }    Resource resource = resourceLoader.getResource(location);    int loadCount = loadBeanDefinitions(resource);    if (actualResources != null)      actualResources.add(resource);    if (this.logger.isDebugEnabled())      this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");    return loadCount;  }


Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);

这个方法可以去看看上面我写的PathMatchingResourcePatternResolver这个类。。你就知道干嘛的了

loadCount = loadBeanDefinitions(resources);

主要看下这个

 public int loadBeanDefinitions(Resource[] resources) throws BeanDefinitionStoreException  {    Assert.notNull(resources, "Resource array must not be null");    int counter = 0;    for (int i = 0; i < resources.length; ++i)      counter += loadBeanDefinitions(resources[i]);    return counter;  }

点开loadBeanDefinitions里进入到BeanDefiitionReader中的方法

public abstract int loadBeanDefinitions(Resource paramResource)    throws BeanDefinitionStoreException;

还是看子类啊

看下XmlBeanDifintionReader

 public int loadBeanDefinitions(Resource resource)    throws BeanDefinitionStoreException  {    return loadBeanDefinitions(new EncodedResource(resource)); } 


 

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()); } 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); } } 


看下doLoadBeanDefinitions这个类

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)    throws BeanDefinitionStoreException  {    int validationMode;    try    {      validationMode = getValidationModeForResource(resource);      Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());      return registerBeanDefinitions(doc, resource);    }    catch (BeanDefinitionStoreException ex) {      throw ex;    }    catch (SAXParseException ex) {      throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);    }    catch (SAXException ex)    {      throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex);    }    catch (ParserConfigurationException ex)    {      throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex);    }    catch (IOException ex)    {      throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex);    }    catch (Throwable ex)    {      throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex);    }  }


看到Document这个类了吗,肯定是dom解析xml吗。。这里我们不用管了。解析xml不是spring的范围。所以不用太在意。下一篇会总结一下。。。其实也不用总结了。。。差不多就是这个过程 。web中也是这样调的。。。。。。。。看懂了这个。。。差不多。。。web也没有问题

个人写得比较详细,第一个是让自己更好的学习,也希望大家有问题可以和我说。。大家一起进步


 

0 0