Spring框架是如何查找方法上的异步任务注解@Async

结论先行

Spring框架层面,查找方法上的注解的原理与机制是一样的。

在方法层面,Spring框架已经找到子类的@Async注解,原因是查找注解会搜索整棵类型继承树,包括超类和实现的接口

异步任务代码示例

`@Async``注解,在父类方法上声明定义。子类覆盖这个方法,但没有声明异步注解。

@Component
public class AsyncParentService {
    @Async
    public String parentAsync() {
        return "parentAsync";
    }
}
@Component
public class AsyncService extends AsyncParentService {
    @Override
    public String parentAsync() {
        return "async";
    }
}

通过Arthas的jad命令反编译指定已加载类的源码。
@Async注解,在子类方法维度的字节码层面,没有继承父类这个注解。
Java字节码

Spring框架是如何查找方法上的注解

事务注解@Transactional等注解,查找原理都是一样的。

注解异步执行拦截者AnnotationAsyncExecutionInterceptor获取执行器bean组件

org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor#getExecutorQualifier

调用 AnnotatedElementUtils.findMergedAnnotation(method, Async.class),返回了@Async注解实例。
AnnotationAsyncExecutionInterceptor.getExecutorQualifier()

public class AnnotationAsyncExecutionInterceptor extends AsyncExecutionInterceptor {
	@Override
	@Nullable
	protected String getExecutorQualifier(Method method) {
		// Maintainer's note: changes made here should also be made in
		// AnnotationAsyncExecutionAspect#getExecutorQualifier
		// 这里返回了异步任务注解实例
		Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
		if (async == null) {
			async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
		}
		return (async != null ? async.value() : null);
	}
}

注解元素工具类AnnotatedElementUtils查找合并的注解

org.springframework.core.annotation.AnnotatedElementUtils#findMergedAnnotation

调用 findAnnotations(element),返回了@Async注解实例。
AnnotatedElementUtils.findMergedAnnotation()

	@Nullable
	public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
		// Shortcut: directly present on the element, with no merging needed?
		if (AnnotationFilter.PLAIN.matches(annotationType) ||
				AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
			return element.getDeclaredAnnotation(annotationType);
		}
		// Exhaustive retrieval of merged annotations...
		return findAnnotations(element) // 这里返回了注解实例
				.get(annotationType, null, MergedAnnotationSelectors.firstDirectlyDeclared())
				.synthesize(MergedAnnotation::isPresent).orElse(null);
	}

查找特定的注解

org.springframework.core.annotation.AnnotatedElementUtils#findAnnotations

其查找策略使用SearchStrategy.TYPE_HIERARCHYPerform a full search of the entire type hierarchy, including superclasses and implemented interfaces.
在方法层面,Spring框架已经找到子类的@Async注解,原因是查找注解会搜索整棵类型继承树,包括超类和实现的接口
AnnotatedElementUtils.findAnnotations()

	private static MergedAnnotations findAnnotations(AnnotatedElement element) {
		return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY, RepeatableContainers.none());
	}

搜索策略
org.springframework.core.annotation.MergedAnnotations.SearchStrategy#TYPE_HIERARCHY

	/**
	 * Search strategies supported by
	 * {@link MergedAnnotations#from(AnnotatedElement, SearchStrategy)} and
	 * variants of that method.
	 *
	 * <p>Each strategy creates a different set of aggregates that will be
	 * combined to create the final {@link MergedAnnotations}.
	 */
	enum SearchStrategy {
		/**
		 * Find only directly declared annotations, without considering
		 * {@link Inherited @Inherited} annotations and without searching
		 * superclasses or implemented interfaces.
		 */
		DIRECT,

		/**
		 * Find all directly declared annotations as well as any
		 * {@link Inherited @Inherited} superclass annotations.
		 */
		INHERITED_ANNOTATIONS,

		/**
		 * Find all directly declared and superclass annotations.
		 */
		SUPERCLASS,

		/**
		 * Perform a full search of the entire type hierarchy, including
		 * superclasses and implemented interfaces.
		 * <p>Superclass annotations do not need to be meta-annotated with
		 * {@link Inherited @Inherited}.
		 */
		TYPE_HIERARCHY,

		/**
		 * Perform a full search of the entire type hierarchy on the source
		 * <em>and</em> any enclosing classes.
		 */
		TYPE_HIERARCHY_AND_ENCLOSING_CLASSES
	}

参考

相关推荐

  1. spring异步@Async方法request丢失问题处理

    2024-06-13 02:02:06       15 阅读
  2. Spring异步注解@Async使用及其自定义线程池配置

    2024-06-13 02:02:06       13 阅读
  3. Spring Boot@Async注解有哪些坑需要避免

    2024-06-13 02:02:06       13 阅读

最近更新

  1. redis中的事务和mysql中的事务有什么区别?

    2024-06-13 02:02:06       0 阅读
  2. C# 构造函数依赖注入 使用out向外传递参数

    2024-06-13 02:02:06       0 阅读
  3. 信息时代,呼唤新的哲学

    2024-06-13 02:02:06       0 阅读
  4. 【数据基础】— B树

    2024-06-13 02:02:06       0 阅读
  5. Vue 路由传参 query方法 bug 记录

    2024-06-13 02:02:06       0 阅读
  6. 翻页 上一页/下一页

    2024-06-13 02:02:06       0 阅读
  7. 前端导出pdf

    2024-06-13 02:02:06       1 阅读
  8. Knife4j的原理及应用详解(五)

    2024-06-13 02:02:06       1 阅读
  9. Day2--每日一练

    2024-06-13 02:02:06       1 阅读

热门阅读

  1. mongo数据迁移方法

    2024-06-13 02:02:06       8 阅读
  2. 防护DDoS攻击出现的常见误区

    2024-06-13 02:02:06       6 阅读
  3. moocast(usaco2016年12月金组第1题)

    2024-06-13 02:02:06       9 阅读
  4. c#与汇川plc通信

    2024-06-13 02:02:06       10 阅读
  5. #07【面试问题整理】嵌入式软件工程师

    2024-06-13 02:02:06       11 阅读
  6. leetcode hot100 之 最长公共子序列

    2024-06-13 02:02:06       10 阅读
  7. SSRF-gopher 协议扩展利用:突破网络限制的利器

    2024-06-13 02:02:06       9 阅读
  8. Ant-Design-Vue 动态表头

    2024-06-13 02:02:06       11 阅读
  9. 深入理解ChatGPT工作原理

    2024-06-13 02:02:06       8 阅读
  10. minio

    minio

    2024-06-13 02:02:06      8 阅读
  11. 代码随想录算法训练营第36期DAY52

    2024-06-13 02:02:06       9 阅读