Spring源碼:@AliasFor JDK動態代理源碼分析

目錄

0. 源碼參見

1. isSynthesizable判斷是否需要被代理

2. SynthesizedAnnotationInvocationHandler創建和執行邏輯

2.1 DefaultAnnotationAttributeExtractor

2.1.1 AbstractAliasAwareAnnotationAttributeExtractor構造函數

2.1.2 接口方法getAttributeValue

2.2 SynthesizedAnnotationInvocationHandler執行邏輯

3. 創建JDK動態代理


我們在使用註解或者自定義註解時,有時經常看到在註解方法上標註註解@AliasFor,見名知義,這是一種爲註解屬性定義別名的註解實現方式,這樣在不同的場合賦值不同的屬性,但獲取兩個屬性值時是一樣的,這裏的實現原理實際上也是JDK動態代理的過程,下面對該代理過程進行分析;

0. 源碼參見

@AliasFor 具體工作機制源碼參見AnnotationUtils.synthesizeAnnotation(A annotation, Object annotatedElement) 方法:

/**
	 * <em>Synthesize</em> an annotation from the supplied {@code annotation}
	 * by wrapping it in a dynamic proxy that transparently enforces
	 * <em>attribute alias</em> semantics for annotation attributes that are
	 * annotated with {@link AliasFor @AliasFor}.
	 * @param annotation the annotation to synthesize
	 * @param annotatedElement the element that is annotated with the supplied
	 * annotation; may be {@code null} if unknown
	 * @return the synthesized annotation if the supplied annotation is
	 * <em>synthesizable</em>; {@code null} if the supplied annotation is
	 * {@code null}; otherwise the supplied annotation unmodified
	 * @throws AnnotationConfigurationException if invalid configuration of
	 * {@code @AliasFor} is detected
	 * @since 4.2
	 * @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
	 * @see #synthesizeAnnotation(Class)
	 */
	public static <A extends Annotation> A synthesizeAnnotation(A annotation, AnnotatedElement annotatedElement) {
		return synthesizeAnnotation(annotation, (Object) annotatedElement);
	}

	@SuppressWarnings("unchecked")
	static <A extends Annotation> A synthesizeAnnotation(A annotation, Object annotatedElement) {
		if (annotation == null) {
			return null;
		}
		if (annotation instanceof SynthesizedAnnotation) {
			return annotation;
		}

		Class<? extends Annotation> annotationType = annotation.annotationType();
		if (!isSynthesizable(annotationType)) {
			return annotation;
		}

		DefaultAnnotationAttributeExtractor attributeExtractor =
				new DefaultAnnotationAttributeExtractor(annotation, annotatedElement);
		InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);

		// Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a
		// synthesizable annotation before (which needs to declare @AliasFor from the same package)
		Class<?>[] exposedInterfaces = new Class<?>[] {annotationType, SynthesizedAnnotation.class};
		return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler);
	}

這裏的處理過程包含如下幾步:

  1. 如果已經是SynthesizedAnnotation實現類,即已經是代理類,直接返回;
  2. isSynthesizable判斷該註解是不是標註了@AliasFor註解,是否需要被代理;
  3. 創建SynthesizedAnnotationInvocationHandler,這是一個InvocationHandler類,用於構造JDK動態代理
  4. 創建JDK動態代理

下面主要分析下2~4步;

1. isSynthesizable判斷是否需要被代理

具體代碼如下:

/**
	 * Determine if annotations of the supplied {@code annotationType} are
	 * <em>synthesizable</em> (i.e., in need of being wrapped in a dynamic
	 * proxy that provides functionality above that of a standard JDK
	 * annotation).
	 * <p>Specifically, an annotation is <em>synthesizable</em> if it declares
	 * any attributes that are configured as <em>aliased pairs</em> via
	 * {@link AliasFor @AliasFor} or if any nested annotations used by the
	 * annotation declare such <em>aliased pairs</em>.
	 * @since 4.2
	 * @see SynthesizedAnnotation
	 * @see SynthesizedAnnotationInvocationHandler
	 */
	@SuppressWarnings("unchecked")
	private static boolean isSynthesizable(Class<? extends Annotation> annotationType) {
		Boolean synthesizable = synthesizableCache.get(annotationType);
		if (synthesizable != null) {
			return synthesizable;
		}

		synthesizable = Boolean.FALSE;
		for (Method attribute : getAttributeMethods(annotationType)) {
			if (!getAttributeAliasNames(attribute).isEmpty()) {
				synthesizable = Boolean.TRUE;
				break;
			}
			Class<?> returnType = attribute.getReturnType();
			if (Annotation[].class.isAssignableFrom(returnType)) {
				Class<? extends Annotation> nestedAnnotationType =
						(Class<? extends Annotation>) returnType.getComponentType();
				if (isSynthesizable(nestedAnnotationType)) {
					synthesizable = Boolean.TRUE;
					break;
				}
			}
			else if (Annotation.class.isAssignableFrom(returnType)) {
				Class<? extends Annotation> nestedAnnotationType = (Class<? extends Annotation>) returnType;
				if (isSynthesizable(nestedAnnotationType)) {
					synthesizable = Boolean.TRUE;
					break;
				}
			}
		}

		synthesizableCache.put(annotationType, synthesizable);
		return synthesizable;
	}

這裏主要判斷依據分爲兩點:

  1. 該註解屬性上直接標註了AliasFor註解;
  2. 屬性返回值爲註解類型且標註了AliasFor註解,該部分的解析是通過遞歸來解析的;

2. SynthesizedAnnotationInvocationHandler創建和執行邏輯

在SynthesizedAnnotationInvocationHandler構造時,首先創建了一個DefaultAnnotationAttributeExtractor,下面首先看一下該類的功能實現,然後再分析SynthesizedAnnotationInvocationHandler的執行過程;

2.1 DefaultAnnotationAttributeExtractor

其繼承結構類圖如下:

接口AnnotationAttributeExtractor是一個註解屬性提取器,主要用來獲取註解的屬性;

AbstractAliasAwareAnnotationAttributeExtractor實現了該接口,主要用於獲取標註AliasFor註解的屬性值;

DefaultAnnotationAttributeExtractor提供了實際獲取屬性值的反射調用方法;

在AbstractAliasAwareAnnotationAttributeExtractor抽象類中,核心邏輯都在構造函數以及getAttributeValue接口方法中,下面分別看下這兩個方法的實現:

2.1.1 AbstractAliasAwareAnnotationAttributeExtractor構造函數

構造函數實現如下:

/**
	 * Construct a new {@code AbstractAliasAwareAnnotationAttributeExtractor}.
	 * @param annotationType the annotation type to synthesize; never {@code null}
	 * @param annotatedElement the element that is annotated with the annotation
	 * of the supplied type; may be {@code null} if unknown
	 * @param source the underlying source of annotation attributes; never {@code null}
	 */
	AbstractAliasAwareAnnotationAttributeExtractor(
			Class<? extends Annotation> annotationType, Object annotatedElement, S source) {

		Assert.notNull(annotationType, "annotationType must not be null");
		Assert.notNull(source, "source must not be null");
		this.annotationType = annotationType;
		this.annotatedElement = annotatedElement;
		this.source = source;
		this.attributeAliasMap = AnnotationUtils.getAttributeAliasMap(annotationType);
	}

最後一行用來獲取原屬性名和別名屬性名之間的對應關係,具體不再展開,實際獲取別名主要包含兩個:

  • 註解類直接包含了兩個互爲別名的屬性;
  • 註解類中兩個屬性的別名同爲該註解元註解的某個屬性,這樣兩個屬性互爲間接別名;

2.1.2 接口方法getAttributeValue

該接口方法主要獲取直接屬性值與所有別名屬性值,並排除默認屬性值之後,返回註解屬性值,具體實現如下:

@Override
	public final Object getAttributeValue(Method attributeMethod) {
		String attributeName = attributeMethod.getName();
		Object attributeValue = getRawAttributeValue(attributeMethod);

		List<String> aliasNames = this.attributeAliasMap.get(attributeName);
		if (aliasNames != null) {
			Object defaultValue = AnnotationUtils.getDefaultValue(this.annotationType, attributeName);
			for (String aliasName : aliasNames) {
				Object aliasValue = getRawAttributeValue(aliasName);

				if (!ObjectUtils.nullSafeEquals(attributeValue, aliasValue) &&
						!ObjectUtils.nullSafeEquals(attributeValue, defaultValue) &&
						!ObjectUtils.nullSafeEquals(aliasValue, defaultValue)) {
					String elementName = (this.annotatedElement != null ? this.annotatedElement.toString() : "unknown element");
					throw new AnnotationConfigurationException(String.format(
							"In annotation [%s] declared on %s and synthesized from [%s], attribute '%s' and its " +
							"alias '%s' are present with values of [%s] and [%s], but only one is permitted.",
							this.annotationType.getName(), elementName, this.source, attributeName, aliasName,
							ObjectUtils.nullSafeToString(attributeValue), ObjectUtils.nullSafeToString(aliasValue)));
				}

				// If the user didn't declare the annotation with an explicit value,
				// use the value of the alias instead.
				if (ObjectUtils.nullSafeEquals(attributeValue, defaultValue)) {
					attributeValue = aliasValue;
				}
			}
		}

		return attributeValue;
	}

2.2 SynthesizedAnnotationInvocationHandler執行邏輯

在接口方法invoke中,代理原目標方法,通過DefaultAnnotationAttributeExtractor獲取屬性值,這樣就綜合考慮了原屬性值和別名屬性值的作用,如下:

@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if (ReflectionUtils.isEqualsMethod(method)) {
			return annotationEquals(args[0]);
		}
		if (ReflectionUtils.isHashCodeMethod(method)) {
			return annotationHashCode();
		}
		if (ReflectionUtils.isToStringMethod(method)) {
			return annotationToString();
		}
		if (AnnotationUtils.isAnnotationTypeMethod(method)) {
			return annotationType();
		}
		if (!AnnotationUtils.isAttributeMethod(method)) {
			throw new AnnotationConfigurationException(String.format(
					"Method [%s] is unsupported for synthesized annotation type [%s]", method, annotationType()));
		}
		return getAttributeValue(method);
	}
	

	private Object getAttributeValue(Method attributeMethod) {
		String attributeName = attributeMethod.getName();
		Object value = this.valueCache.get(attributeName);
		if (value == null) {
			value = this.attributeExtractor.getAttributeValue(attributeMethod);
			if (value == null) {
				String msg = String.format("%s returned null for attribute name [%s] from attribute source [%s]",
						this.attributeExtractor.getClass().getName(), attributeName, this.attributeExtractor.getSource());
				throw new IllegalStateException(msg);
			}

			// Synthesize nested annotations before returning them.
			if (value instanceof Annotation) {
				value = AnnotationUtils.synthesizeAnnotation((Annotation) value, this.attributeExtractor.getAnnotatedElement());
			}
			else if (value instanceof Annotation[]) {
				value = AnnotationUtils.synthesizeAnnotationArray((Annotation[]) value, this.attributeExtractor.getAnnotatedElement());
			}

			this.valueCache.put(attributeName, value);
		}

		// Clone arrays so that users cannot alter the contents of values in our cache.
		if (value.getClass().isArray()) {
			value = cloneArray(value);
		}

		return value;
	}

3. 創建JDK動態代理

創建JDK動態代理還是通過Proxy.newProxyInstance來實現的,在目標接口中加入了SynthesizedAnnotation接口,該接口是一個marker接口,表示是否已經解析爲代理對象;

Class<?>[] exposedInterfaces = new Class<?>[] {annotationType, SynthesizedAnnotation.class}; (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章