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

结论先行

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

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

异步任务代码示例

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

java 复制代码
@Component
public class AsyncParentService {
    @Async
    public String parentAsync() {
        return "parentAsync";
    }
}
java 复制代码
@Component
public class AsyncService extends AsyncParentService {
    @Override
    public String parentAsync() {
        return "async";
    }
}

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

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

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

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

org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor#getExecutorQualifier

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

java 复制代码
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注解实例。

java 复制代码
	@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注解,原因是查找注解会搜索整棵类型继承树,包括超类和实现的接口

java 复制代码
	private static MergedAnnotations findAnnotations(AnnotatedElement element) {
		return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY, RepeatableContainers.none());
	}

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

java 复制代码
	/**
	 * 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
	}

参考

相关推荐
2401_854391089 分钟前
Spring Boot大学生就业招聘系统的开发与部署
java·spring boot·后端
杨荧36 分钟前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源
2401_857610031 小时前
SpringBoot实现:校园资料分享平台开发指南
服务器·spring boot·php
这孩子叫逆1 小时前
Spring Boot项目的创建与使用
java·spring boot·后端
Jay_fearless2 小时前
Redis SpringBoot项目学习
spring boot·redis
coderWangbuer2 小时前
基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)
spring boot·后端·sql
Kenny.志2 小时前
2、Spring Boot 3.x 集成 Feign
java·spring boot·后端
sky丶Mamba3 小时前
Spring Boot中获取application.yml中属性的几种方式
java·spring boot·后端
千里码aicood4 小时前
【2025】springboot教学评价管理系统(源码+文档+调试+答疑)
java·spring boot·后端·教学管理系统
程序员-珍4 小时前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发