结论先行
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
注解,在子类方法维度的字节码层面,没有继承父类这个注解。
Spring框架是如何查找方法上的注解
事务注解
@Transactional
等注解,查找原理都是一样的。
注解异步执行拦截者AnnotationAsyncExecutionInterceptor获取执行器bean组件
org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor#getExecutorQualifier
调用 AnnotatedElementUtils.findMergedAnnotation(method, Async.class),返回了@Async
注解实例。
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
注解实例。
@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_HIERARCHY
,Perform a full search of the entire type hierarchy, including superclasses and implemented interfaces.
在方法层面,Spring框架已经找到子类的@Async注解,原因是查找注解会搜索整棵类型继承树,包括超类和实现的接口。
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
}
参考
- jad - 反编译指定已加载类的源码 – Arthas命令