/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */ @Override protected final void refreshBeanFactory() throws BeansException { //在这里,如果创建了BeanFactory就销毁并关闭BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //这里是创建并设置持有的DefaultListableBeanFactory的地方同时调用loadBeanDefinition状态bean定义 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); } }
上面createBeanFactory
/** * 这里是创建DefaultListableBeanFactory 地地方,用getInternalParentBeanFactory()的具体实现可以参看 * @see AbstractApplicationContext#getInternalParentBeanFactory() 的实现,会根据已有的双亲IOC容器 * 信息生成DefaultListableBeanFactory的双亲Ioc容器 * @return */ protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }
loadBeanDefinitions 是个抽象方法,具体实现交给子类完成
/** * BeanDefinitionReader载入Bean定义,具体实现委托子类完成 * @param beanFactory * @throws BeansException * @throws IOException */ protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException;
具体子类
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException { //这里取得ResourceLoader用的是DefaultResourceLoader ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available"); } //这里对Resource的路径进行解析,这些Resource指向BeanDefinition信息 if (resourceLoader instanceof ResourcePatternResolver) { // Resource pattern matching available. try { Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int loadCount = loadBeanDefinitions(resources); if (actualResources != null) { for (Resource resource : resources) { actualResources.add(resource); } } if (logger.isDebugEnabled()) { 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); } } else { // Can only load single resources by absolute URL. Resource resource = resourceLoader.getResource(location); int loadCount = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]"); } return loadCount; } }
再来看看getResource,他的具体实现在DefaultResourceLoader里
public Resource getResource(String location) { Assert.notNull(location, "Location must not be null"); //处理带有classpath标示的Resource if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } else { try { // Try to parse the location as a URL... //处理URL标示的Resource URL url = new URL(location); return new UrlResource(url); } catch (MalformedURLException ex) { // No URL -> resolve as resource path. //如果既不是classpath的Resource 又不是url的Resource, //重新交给getResourceByPath,这个方法是一个protected方法,默认实现是得到 //一个ClassPathContextResource,这个方法常常会用子类实现 return getResourceByPath(location); } } }