Spring源码分析之Scope注解处理

前言

本文旨在分析在Spring容器启动之时,@Scope注解的处理过程

处理代码为:(该代码来自与register方法的底层实现doRegisterBean方法)

ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());

//进入this.scopeMetadataResolver.resolveScopeMetadata方法
ScopeMetadata resolveScopeMetadata(BeanDefinition definition);

//找到resolveScopeMetadata(BeanDefinition definition)方法的实现如下:


@Override
	public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
		ScopeMetadata metadata = new ScopeMetadata();
//判断definition是AnnotatedBeanDefinition的实例,按照本人工程中写出的样例其中传入的definition参数的类型是AnnotatedGenericBeanDefinition,
//AnnotatedGenericBeanDefinition的继承关系图如下1.1中所示
//结论是true
		if (definition instanceof AnnotatedBeanDefinition) {
			AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;//强装
           //AnnotationConfigUtils.attributesFor方法分析如下1.2所示
           //其作用为:在待注入bean中寻找@Scope注解
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
					annDef.getMetadata(), this.scopeAnnotationType); //Scope.class就是this.scopeAnnotationType
            //如果存在@Scope注解
			if (attributes != null) {
                //attributes.getString("value")作用就是得出@Scope注解后的value值
                //就是将value中的值赋给scopeName属性
				metadata.setScopeName(attributes.getString("value"));
                //获取 proxyMode 属性值
				ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
                //如果代理模式是默认的,则proxyMode=ScopedProxyMode.NO,没代理
				if (proxyMode == ScopedProxyMode.DEFAULT) {
					proxyMode = this.defaultProxyMode;
				}
                //设置代理模式
				metadata.setScopedProxyMode(proxyMode);
			}
		}
		return metadata;
	}

1.1

AnnotatedGenericBeanDefinition的继承关系图如下所示:

显而易见,AnnotatedGenericBeanDefinition继承于BeanDifinition,故而前述的判断为true。

1.2 

AnnotationConfigUtils.attributesFor方法源码:

@Nullable
	static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
		return attributesFor(metadata, annotationClass.getName());
	}


//上述方法的重载方法:attributesFor(metadata, annotationClass.getName())源码:


@Nullable
	static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
		return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
	}

//继续追踪AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false))方法如下:
//1.参数中的方法:metadata.getAnnotationAttributes(annotationClassName, false)
//详细分析见1.3


//2.主方法:其中包装进入AnnotationAttributes这个Map类中的实例map是参数中方法提供的,所以所有的逻辑来自于该参数方法

/**
	 * Return an {@link AnnotationAttributes} instance based on the given map.
	 * <p>If the map is already an {@code AnnotationAttributes} instance, it
	 * will be cast and returned immediately without creating a new instance.
	 * Otherwise a new instance will be created by passing the supplied map
	 * to the {@link #AnnotationAttributes(Map)} constructor.
	 * @param map original source of annotation attribute <em>key-value</em> pairs
      翻译大概是:基于所给定的map返回一个AnnotationAttributes类的实例
      如果这个map已经是一个AnnotationAttributes类的实例,它将被强转,并在不创建一个新的实例的
      前提下立马返回,程序结束,否则呢,就将该map传递给AnnotationAttributes的构造器创建一个 
      AnnotationAttributes类的新实例。
	 */,
	@Nullable
	public static AnnotationAttributes fromMap(@Nullable Map<String, Object> map) {
       //下面的逻辑在翻译中已经体现,不再赘述
		if (map == null) {
			return null;
		}
		if (map instanceof AnnotationAttributes) {
			return (AnnotationAttributes) map;
		}
		return new AnnotationAttributes(map);
	}

1.3

metadata.getAnnotationAttributes(annotationClassName, false)源码

/**
	 * Retrieve the attributes of the annotation of the given type, if any (i.e. if
	 * defined on the underlying element, as direct annotation or meta-annotation),
	 * also taking attribute overrides on composed annotations into account.
	 * @param annotationName the fully qualified class name of the annotation
	 * type to look for
	 * @param classValuesAsString whether to convert class references to String
	 * class names for exposure as values in the returned Map, instead of Class
	 * references which might potentially have to be loaded first
	 * @return a Map of attributes, with the attribute name as key (e.g. "value")
	 * and the defined attribute value as Map value. This return value will be
	 * {@code null} if no matching annotation is defined.
     * 主要的意思是,检索出所给定注释的属性
	 */
	@Nullable
	Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);


//查看其实现方法,鼠标指针放在方法上,快捷键Ctrl+Alt+B,出现所有的实现方法,最后点击你所需要的

###StandardAnnotationMetadata类
@Override
	@Nullable
	public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) { //classValuesAsString=false
		return (this.annotations.length > 0 ? AnnotatedElementUtils.getMergedAnnotationAttributes(
				getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap) : null); 
 //1.annotations为final类型的数组,并且在StandardAnnotationMetadata类的构造器中赋值为:
 //this.annotations = introspectedClass.getAnnotations();
 //追踪introspectedClass.getAnnotations底层如下(****)处
	}
 //2.getAnnotationAttributes(String annotationName, boolean classValuesAsString)的逻辑是:
(1)annotations数组长度大于0,则执行AnnotatedElementUtils.getMergedAnnotationAttributes(
				getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap)方法,
分析如下1.4所示。
(2)否则,返回null,也就是说待处理的bean中没有注释


(****)introspectedClass.getAnnotations底层实现:
public Annotation[] getAnnotations() {
        return AnnotationParser.toArray(annotationData().annotations); //得到一个Annotation[]实例,其底层待探索(反射实现)
    }

1.4

AnnotatedElementUtils.getMergedAnnotationAttributes(
                getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap)源码:

/**
	 * Get the first annotation of the specified {@code annotationName} within
	 * the annotation hierarchy <em>above</em> the supplied {@code element} and
	 * merge that annotation's attributes with <em>matching</em> attributes from
	 * annotations in lower levels of the annotation hierarchy.
	 * <p>Attributes from lower levels in the annotation hierarchy override attributes
	 * of the same name from higher levels, and {@link AliasFor @AliasFor} semantics are
	 * fully supported, both within a single annotation and within the annotation hierarchy.
	 * <p>In contrast to {@link #getAllAnnotationAttributes}, the search algorithm used by
	 * this method will stop searching the annotation hierarchy once the first annotation
	 * of the specified {@code annotationName} has been found. As a consequence,
	 * additional annotations of the specified {@code annotationName} will be ignored.
	 * <p>This method follows <em>get semantics</em> as described in the
	 * {@linkplain AnnotatedElementUtils class-level javadoc}.
	 * @param element the annotated element
	 * @param annotationName the fully qualified class name of the annotation type to find
	 * @param classValuesAsString whether to convert Class references into Strings or to
	 * preserve them as Class references
	 * @param nestedAnnotationsAsMap whether to convert nested Annotation instances
	 * into {@code AnnotationAttributes} maps or to preserve them as Annotation instances
	 * @return the merged {@code AnnotationAttributes}, or {@code null} if not found
	 * @since 4.2
	 * @see #findMergedAnnotation(AnnotatedElement, Class)
	 * @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
	 * @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
	 */
      //上述翻译的核心意思是:在提供的element之上的注释层次结构中,获取指定annotationName的第一个注释,
      //并将该注释的属性与来自注释层次结构较低级别的注释的匹配属性合并。
      //在本案例中传递的参数可知:就是获取@Scope注释的属性等信息。
	@Nullable
	public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
			String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
		AnnotationAttributes attributes = searchWithGetSemantics(element, null, annotationName,
				new MergedAnnotationAttributesProcessor(classValuesAsString, nestedAnnotationsAsMap)); 
       //核心方法,获取attribute属性,可以看下searchWithGetSemantics方法的底层描述,详见1.5
		AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
		return attributes;
	}

1.5

searchWithGetSemantics方法的底层描述

	/**
	 * Search for annotations of the specified {@code annotationName} or
	 * {@code annotationType} on the specified {@code element}, following
	 * <em>get semantics</em>.
	 * @param element the annotated element
	 * @param annotationType the annotation type to find
	 * @param annotationName the fully qualified class name of the annotation
	 * type to find (as an alternative to {@code annotationType})
	 * @param processor the processor to delegate to
	 * @return the result of the processor (potentially {@code null})

     * 大致意思是:在遵循get语义的前提下,在指定element实例上寻找指定的annotationName或者
     * annotationType的注释,由上面传递的参数可知,我们的目的就是寻找@Scope注释
	 */
	@Nullable
	private static <T> T searchWithGetSemantics(AnnotatedElement element,
			@Nullable Class<? extends Annotation> annotationType,
			@Nullable String annotationName, Processor<T> processor) {

		return searchWithGetSemantics(element,
				(annotationType != null ? Collections.singleton(annotationType) : Collections.emptySet()),
				annotationName, null, processor);
	}

//在往下的searchWithGetSemantics方法(org.springframework.core.annotation.AnnotatedElementUtils#searchWithGetSemantics(java.lang.reflect.AnnotatedElement, java.util.Set<java.lang.Class<? extends java.lang.annotation.Annotation>>, 
java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>, org.springframework.core.annotation.AnnotatedElementUtils.Processor<T>, java.util.Set<java.lang.reflect.AnnotatedElement>, int))
大概是用递归实现的,有待进一步探究

1.6 参考文献

【1】https://segmentfault.com/a/1190000017413393?utm_source=tag-newest

【2】https://www.bilibili.com/video/BV1tx411o77Z?p=5

【3】《Spring源码解析》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值