SFフレームワークを学ぼうシリーズ 5.8-spring-Beans-アノテーション付きBean解析1-解析入口

Spring フレームワークが XML モード設定の Bean 解析をどのように解析するかを以前に追跡しました (「SF Framework Together シリーズ 5.7 を学ぶ - モジュール Beans-BeanDefinition 解析」を参照)。この記事では主にアノテーション Bean を分析します (「SF Framework Together シリーズ 5.2 を学ぶ - 」を参照)。 Module Beans- 詳細については、「Bean メタデータ構成」) が Spring フレームワークによって解析される方法を参照してください。

アノテーションの設定

アノテーション Bean の構成は次のとおりです。

	<!-- 配置注解模式 -->
	<context:annotation-config/>
	<!-- 注解模式:配置bean扫描路径 -->
	<context:component-scan base-package="com.learnsf.main,com.learnsf.service,com.learnsf.demo"/>

エントリを解析中

アノテーション解析の開始点は、以下に示すように DefaultBeanDefinitionDocumentReader.parseBeanDefinitions です。
ここに画像の説明を挿入します
ここで、XML 解析はメソッド parseDefaultElement(ele, delegate) です。
これまでのエントリーの流れは「SF Framework Series 5.7 - モジュールBeans - BeanDefinition解析をまとめて学ぶ」を参照してください。

解析プロセス

ここに画像の説明を挿入します
注: NamespaceHandlerSupport は、異なる名前空間に従って異なるパーサーを選択します。SF には次の NamespaceHandler があります。
ここに画像の説明を挿入します
アノテーション Bean によって使用される名前空間は「context」であり、対応する NamespaceHandler は ContextNamespaceHandler です。

コード追跡

BeanDefinitionParserDelegate.parseCustomElement(要素要素)

デフォルト以外の名前空間で定義された要素を解決します。

	//过渡类
	@Nullable
	public BeanDefinition parseCustomElement(Element ele) {
    
    
		return parseCustomElement(ele, null);
	}

	// 解析一个非默认命名空间定义的元素
	@Nullable
	public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    
    
		// 获取命名空间资源符
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
    
    
			return null;
		}
		// 根据命名空间资源符获得对应的解析器 注1
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
    
    
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		// 解析器解析
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

注 1: 使用される NamespaceHandler は、namespaceUri に従って解析され、異なる名前空間は異なる NamespaceHandler に対応します。正しい NamespaceHandler を見つける方法は、NamespaceHandlerResolver (DefaultNamespaceHandlerResolver) を通じて行われます。

DefaultNamespaceHandlerResolver.resolve(String namespaceUri)

namespaceUri に基づいて使用される NamespaceHandler を解析します。

	@Override
	@Nullable
	public NamespaceHandler resolve(String namespaceUri) {
    
    
		// 根据namespaceUri从缓存获取handler
		Map<String, Object> handlerMappings = getHandlerMappings();
		Object handlerOrClassName = handlerMappings.get(namespaceUri);
		if (handlerOrClassName == null) {
    
    
			// 没有对应的handler
			return null;
		}
		else if (handlerOrClassName instanceof NamespaceHandler namespaceHandler) {
    
    
			// 如果handler是NamespaceHandler,直接返回
			return namespaceHandler;
		}
		else {
    
    
			/* 如果handler不是NamespaceHandler(则是NamespaceHandler的className),则生成 */
			String className = (String) handlerOrClassName;
			try {
    
    
				// 加载NamespaceHandler Class
				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初始化 注1
				namespaceHandler.init();
				// 放入缓存
				handlerMappings.put(namespaceUri, namespaceHandler);
				return namespaceHandler;
			}
			catch (ClassNotFoundException ex) {
    
    
				throw new FatalBeanException("Could not find NamespaceHandler class [" + className +
						"] for namespace [" + namespaceUri + "]", ex);
			}
			catch (LinkageError err) {
    
    
				throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +
						className + "] for namespace [" + namespaceUri + "]", err);
			}
		}
	}

注 1: ここでの NamespaceHandler は ContextNamespaceHandler であり、コードは次のとおりです。

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
    
    

	@Override
	public void init() {
    
    
		registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
		registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
		registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
		registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
		registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
	}

}

コードからわかるように、ContextNamespaceHandler は NamespaceHandlerSupport を継承し、ネームスペースでサポートされるさまざまな要素 BeanDefinition パーサーを登録するための init() メソッドのみを提供します。

NamespaceHandlerSupport.parse(Element 要素、ParserContext parserContext)

解析する要素に対応する BeanDefinitionParser パーサーを見つけます。
前の ContextNamespaceHandler.init() からわかるように、
要素 annotation-config は AnnotationConfigBeanDefinitionParser に対応し
、要素 common-scan は ComponentScanBeanDefinitionParser に対応します。

	@Override
	@Nullable
	public BeanDefinition parse(Element element, ParserContext parserContext) {
    
    
		// 找元素对应的解析器:BeanDefinitionParser 
		BeanDefinitionParser parser = findParserForElement(element, parserContext);
		// 根据元素解析bean 注1
		return (parser != null ? parser.parse(element, parserContext) : null);
	}

	@Nullable
	private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
    
    
		String localName = parserContext.getDelegate().getLocalName(element);
		BeanDefinitionParser parser = this.parsers.get(localName);
		if (parser == null) {
    
    
			parserContext.getReaderContext().fatal(
					"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
		}
		return parser;
	}

注 1: 異なる要素は異なるパーサーに対応する場合があります。たとえば、
要素 context:annotation-config は AnnotationConfigBeanDefinitionParser に対応します。解析方法の詳細については、「SF フレームワーク シリーズを一緒に学ぶ 5.8 - モジュール Bean - アノテーション Bean の解析 2 - 解析」を参照してください。 annotation-config ";
要素 context:component-scan は、ComponentScanBeanDefinitionParser に対応します。解析方法の詳細については、「SF フレームワークシリーズを学ぶ 5.8 - モジュール Beans - Bean アノテーションの解析 3 - コンポーネントの解析」を参照してください。

おすすめ

転載: blog.csdn.net/davidwkx/article/details/131643597