四、obtainFreshBeanFactory方法解析

代码:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法
		//重新实例化一个DefaultListableBeanFactory,加载xml配置,生成BeanDefinitions
		refreshBeanFactory();
		//返回刚刚实例化的DefaultListableBeanFactory
		return getBeanFactory();
	}

refreshBeanFactory会创建DefaultListableBeanFactory对象,然后调用loadBeanDefinitions方法

	protected final void refreshBeanFactory() throws BeansException {
		//如果beanFactory已经有了值,就将其清空,重新构建
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建DefaultListableBeanFactory对象,并赋值给beanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			//加载BeanDefinitions(基于tomcat的web.xml启动时,默认是调用XmlWebApplicationContext读取xml中配置的bean)
			loadBeanDefinitions(beanFactory);
			//赋值
			this.beanFactory = beanFactory;
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

getBeanFactory方法就是把刚刚赋值给beanFactory的DefaultListableBeanFactory对象返回.

	public final ConfigurableListableBeanFactory getBeanFactory() {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory == null) {
			throw new IllegalStateException("BeanFactory not initialized or already closed - " +
					"call 'refresh' before accessing beans via the ApplicationContext");
		}
		return beanFactory;
	}

接下来就是看loadBeanDefinitions方法

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		
		// 为给定的BeanFactory创建一个新的XmlBeanDefinitionReader。
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		
		// 使用此上下文的资源加载环境配置bean定义阅读器。
		beanDefinitionReader.setEnvironment(getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		
		//允许一个子类提供自定义的读取器初始化,然后继续实际加载bean定义。
		initBeanDefinitionReader(beanDefinitionReader);
		//加载BeanDefinitions
		loadBeanDefinitions(beanDefinitionReader);
	}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
		//xml配置路径
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				//读取xml配置
				reader.loadBeanDefinitions(configLocation);
			}
		}
	}
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available. 可用的资源模式匹配。
			try {
				//将资源解析为Resource
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				//解析resources,加载BeanDefinitions
				int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}
				return count;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resources by absolute URL. 只能通过绝对URL加载单个资源。
			Resource resource = resourceLoader.getResource(location);
			int count = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
			}
			return count;
		}
	}
@Override
	public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int count = 0;
		for (Resource resource : resources) {
			//加载BeanDefinitions
			count += loadBeanDefinitions(resource);
		}
		return count;
	}
@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		//EncodedResource对资源文件的编码格式进行处理
		return loadBeanDefinitions(new EncodedResource(resource));
	}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}
		//通过属性来记录已经加载的资源
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		//获取输入流
		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
			InputSource inputSource = new InputSource(inputStream);
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			//加载bean定义。(核心部分)
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

接下来的代码量有的大,我就不写出来了,大家想了解的话可以看看《spring源码深度解析 第2版》,里面有详细讲解。
下一章:五、BeanFactoryPostProcessor方法解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值