Spring如何通过定义在META-INF/spring.handlers中的属性进行配置文件解析

毫无疑问这些东西肯定在Spring的入口函数refresh()之中进行的。

AbstractApplicationContext

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//获得一个新的beanFactory,并进行一些相关的load
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();//通知子类context刷新内部的BeanFactory
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}
AbstractRefreshableApplicationContext
protected final void refreshBeanFactory() throws BeansException {
		if (hasBeanFactory()) {
			destroyBeans();//销毁当前context管理的所有bean
			closeBeanFactory();//关闭beanFactory
		}
		try {//创建一个新的beanFactory(DefaultListableBeanFactory)
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			loadBeanDefinitions(beanFactory);//加载BeanDefinition
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
//...
	}

XmlWebApplicationContext

	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
                //创建一个新的XmlBeanDefinitionReader
		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);//接着加载BeanDefinition
	}
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
		String[] configLocations = getConfigLocations();//获得ServletConfig的配置文件位置
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				reader.loadBeanDefinitions(configLocation);//根据位置加载BeanDefinition
			}
		}
	}

中间省略

XmlBeanDefinitionReader

	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(this.getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//创建一个ReaderContext,
                //注册BeanDefinition
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
	protected XmlReaderContext createReaderContext(Resource resource) {
		if (this.namespaceHandlerResolver == null) {//创建默认的名称控件处理器解析器
			this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
		}//返回创建好的xmlReaderContext,将创建好的namespaceHandlerResolver传入
		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
				this.sourceExtractor, this, this.namespaceHandlerResolver);
	}
	protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {//对应的NamespaceHandlerResolver
		return new DefaultNamespaceHandlerResolver(getResourceLoader().getClassLoader());
	}
	public DefaultNamespaceHandlerResolver(ClassLoader classLoader) {
		this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);//这个位置就在META-INF/spring.handlers
	}

接着往下走注册BeanDefinitioni的过程

DefaultBeanDefinitionDocumentReader

	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);//注册beanDefinition 将root根节点传入
	}
	protected void doRegisterBeanDefinitions(Element root) {
//....
		this.delegate = createDelegate(this.readerContext, root, parent);//创建一个委托

		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);//处理
		postProcessXml(root);

		this.delegate = parent;
	}

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);//解析自定义的节点
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}



	public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {//null
		String namespaceUri = getNamespaceURI(ele);//根据之前设置的解析器对这个uri进行解析,获得一个NamespaceHandler
                //通过键值对的形式存在文件里面,在resolve里面对类名获取,然后实例化一个handler对象
                 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
//....现在可以对配置文件进行解析了。
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}
DefaultNamespaceHandlerResolver
	public NamespaceHandler resolve(String namespaceUri) {
		Map<String, Object> handlerMappings = getHandlerMappings();
		Object handlerOrClassName = handlerMappings.get(namespaceUri);//获取处理器的类名
		if (handlerOrClassName == null) {
			return null;
		}
		else if (handlerOrClassName instanceof NamespaceHandler) {
			return (NamespaceHandler) handlerOrClassName;
		}
		else {
			String className = (String) handlerOrClassName;
			try {//利用反射根据类名进行类的装载
				Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
				if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
					throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
							"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
				}//根据类进行实例化
				NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
				namespaceHandler.init();
				handlerMappings.put(namespaceUri, namespaceHandler);//缓存这个handler,下次其他的可以再次利用
				return namespaceHandler;
			}
//....
		}
	}




阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页