You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
source-code-hunter/docs/Spring/clazz/Spring-Metadata.md

996 lines
25 KiB

# Spring 元信息
- Author: [HuiFer](https://github.com/huifer)
- 源码阅读仓库: [SourceHot-Spring](https://github.com/SourceHot/spring-framework-read)
## ClassMetadata
```java
public interface ClassMetadata {
/**
* 类名
*/
String getClassName();
/**
* 是否是接口
*/
boolean isInterface();
/**
* 是否是注解
*/
boolean isAnnotation();
/**
* 是否是超类
*/
boolean isAbstract();
/**
* 是否允许创建,实例化
*/
default boolean isConcrete() {
return !(isInterface() || isAbstract());
}
/**
* 是否有final修饰
*/
boolean isFinal();
/**
* 是否独立
*/
boolean isIndependent();
/**
* 是否有内部类
*/
default boolean hasEnclosingClass() {
return (getEnclosingClassName() != null);
}
/**
* 是否是基础类
*/
@Nullable
String getEnclosingClassName();
/**
* 是否有父类
*/
default boolean hasSuperClass() {
return (getSuperClassName() != null);
}
/**
* 父类名称
*/
@Nullable
String getSuperClassName();
/**
* 实现类名称列表
*/
String[] getInterfaceNames();
/**
* 成员列表
* @since 3.1
*/
String[] getMemberClassNames();
}
```
![image-20200824094154847](/images/spring/image-20200824094154847.png)
## AnnotatedTypeMetadata
```java
public interface AnnotatedTypeMetadata {
/**
* 获取所有注解
*/
MergedAnnotations getAnnotations();
/**
* 是否有注解
*/
default boolean isAnnotated(String annotationName) {
return getAnnotations().isPresent(annotationName);
}
/**
* 获取注解的属性
*/
@Nullable
default Map<String, Object> getAnnotationAttributes(String annotationName) {
return getAnnotationAttributes(annotationName, false);
}
// 省略其他
}
```
## AnnotationMetadata
```java
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
/**
* 获取注解名称,全类名
*/
default Set<String> getAnnotationTypes() {
return getAnnotations().stream()
.filter(MergedAnnotation::isDirectlyPresent)
.map(annotation -> annotation.getType().getName())
.collect(Collectors.toCollection(LinkedHashSet::new));
}
/**
* 注解全类名
*/
default Set<String> getMetaAnnotationTypes(String annotationName) {
MergedAnnotation<?> annotation = getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent);
if (!annotation.isPresent()) {
return Collections.emptySet();
}
return MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream()
.map(mergedAnnotation -> mergedAnnotation.getType().getName())
.collect(Collectors.toCollection(LinkedHashSet::new));
}
/**
* 是否包含某个注解
*/
default boolean hasAnnotation(String annotationName) {
return getAnnotations().isDirectlyPresent(annotationName);
}
/**
* 是否被某个注解标记过
*/
default boolean hasMetaAnnotation(String metaAnnotationName) {
return getAnnotations().get(metaAnnotationName,
MergedAnnotation::isMetaPresent).isPresent();
}
/**
* 是否有注解,类里面有一个注解就返回true
*/
default boolean hasAnnotatedMethods(String annotationName) {
return !getAnnotatedMethods(annotationName).isEmpty();
}
/**
* 获取包含注解的方法
*/
Set<MethodMetadata> getAnnotatedMethods(String annotationName);
/**
* 通过反射创建一个注解的元信息
*/
static AnnotationMetadata introspect(Class<?> type) {
return StandardAnnotationMetadata.from(type);
}
}
```
## MethodMetadata
```java
public interface MethodMetadata extends AnnotatedTypeMetadata {
/**
* 方法名称
*/
String getMethodName();
/**
* 方法全路径
*/
String getDeclaringClassName();
/**
* 返回值类型
*/
String getReturnTypeName();
/**
* 是不是abstrac修饰
*/
boolean isAbstract();
/**
* 是否 static 修饰
*/
boolean isStatic();
/**
* 是否 final 修饰
*/
boolean isFinal();
/**
* 是否重载
*/
boolean isOverridable();
}
```
## MetadataReader
```java
public interface MetadataReader {
/**
* Return the resource reference for the class file.
*
* 获取资源
*/
Resource getResource();
/**
* Read basic class metadata for the underlying class.
* 获取类的元信息
*/
ClassMetadata getClassMetadata();
/**
* Read full annotation metadata for the underlying class,
* including metadata for annotated methods.
*
* 获取注解的元信息
*/
AnnotationMetadata getAnnotationMetadata();
}
```
## MetadataReaderFactory
- 用来创建 MetadataReader
```java
public interface MetadataReaderFactory {
/**
* Obtain a MetadataReader for the given class name.
* @param className the class name (to be resolved to a ".class" file)
* @return a holder for the ClassReader instance (never {@code null})
* @throws IOException in case of I/O failure
*/
MetadataReader getMetadataReader(String className) throws IOException;
/**
* Obtain a MetadataReader for the given resource.
* @param resource the resource (pointing to a ".class" file)
* @return a holder for the ClassReader instance (never {@code null})
* @throws IOException in case of I/O failure
*/
MetadataReader getMetadataReader(Resource resource) throws IOException;
}
```
- 接口解释的差不多了.接下来看一些实现
## StandardClassMetadata
- 通过JAVA 反射来获取类的元信息
- 这个类采用的方式是Java class的方法,通过构造方法来填写一个Class对象. 之后使用这个对象的方法
```java
public class StandardClassMetadata implements ClassMetadata {
private final Class<?> introspectedClass;
@Deprecated
public StandardClassMetadata(Class<?> introspectedClass) {
Assert.notNull(introspectedClass, "Class must not be null");
this.introspectedClass = introspectedClass;
}
/**
* Return the underlying Class.
*/
public final Class<?> getIntrospectedClass() {
return this.introspectedClass;
}
@Override
public String getClassName() {
return this.introspectedClass.getName();
}
@Override
public boolean isInterface() {
return this.introspectedClass.isInterface();
}
@Override
public boolean isAnnotation() {
return this.introspectedClass.isAnnotation();
}
@Override
public boolean isAbstract() {
return Modifier.isAbstract(this.introspectedClass.getModifiers());
}
@Override
public boolean isFinal() {
return Modifier.isFinal(this.introspectedClass.getModifiers());
}
@Override
public boolean isIndependent() {
return (!hasEnclosingClass() ||
(this.introspectedClass.getDeclaringClass() != null &&
Modifier.isStatic(this.introspectedClass.getModifiers())));
}
@Override
@Nullable
public String getEnclosingClassName() {
Class<?> enclosingClass = this.introspectedClass.getEnclosingClass();
return (enclosingClass != null ? enclosingClass.getName() : null);
}
@Override
@Nullable
public String getSuperClassName() {
Class<?> superClass = this.introspectedClass.getSuperclass();
return (superClass != null ? superClass.getName() : null);
}
@Override
public String[] getInterfaceNames() {
Class<?>[] ifcs = this.introspectedClass.getInterfaces();
String[] ifcNames = new String[ifcs.length];
for (int i = 0; i < ifcs.length; i++) {
ifcNames[i] = ifcs[i].getName();
}
return ifcNames;
}
@Override
public String[] getMemberClassNames() {
LinkedHashSet<String> memberClassNames = new LinkedHashSet<>(4);
for (Class<?> nestedClass : this.introspectedClass.getDeclaredClasses()) {
memberClassNames.add(nestedClass.getName());
}
return StringUtils.toStringArray(memberClassNames);
}
}
```
## StandardMethodMetadata
- 通过java反射获取方法的元信息
- 构造方法传递一个method
- 如果这个方法有注解,会进行注解的解析
```java
public class StandardMethodMetadata implements MethodMetadata {
private final Method introspectedMethod;
private final boolean nestedAnnotationsAsMap;
private final MergedAnnotations mergedAnnotations;
@Deprecated
public StandardMethodMetadata(Method introspectedMethod) {
this(introspectedMethod, false);
}
@Deprecated
public StandardMethodMetadata(Method introspectedMethod, boolean nestedAnnotationsAsMap) {
Assert.notNull(introspectedMethod, "Method must not be null");
this.introspectedMethod = introspectedMethod;
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
this.mergedAnnotations = MergedAnnotations.from(
introspectedMethod, SearchStrategy.DIRECT, RepeatableContainers.none());
}
@Override
public MergedAnnotations getAnnotations() {
return this.mergedAnnotations;
}
/**
* Return the underlying Method.
*/
public final Method getIntrospectedMethod() {
return this.introspectedMethod;
}
@Override
public String getMethodName() {
return this.introspectedMethod.getName();
}
@Override
public String getDeclaringClassName() {
return this.introspectedMethod.getDeclaringClass().getName();
}
@Override
public String getReturnTypeName() {
return this.introspectedMethod.getReturnType().getName();
}
@Override
public boolean isAbstract() {
return Modifier.isAbstract(this.introspectedMethod.getModifiers());
}
@Override
public boolean isStatic() {
return Modifier.isStatic(this.introspectedMethod.getModifiers());
}
@Override
public boolean isFinal() {
return Modifier.isFinal(this.introspectedMethod.getModifiers());
}
@Override
public boolean isOverridable() {
return !isStatic() && !isFinal() && !isPrivate();
}
private boolean isPrivate() {
return Modifier.isPrivate(this.introspectedMethod.getModifiers());
}
@Override
@Nullable
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
if (this.nestedAnnotationsAsMap) {
return MethodMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString);
}
return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod,
annotationName, classValuesAsString, false);
}
/**
* 获取所有注解的信息
*/
@Override
@Nullable
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
if (this.nestedAnnotationsAsMap) {
return MethodMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString);
}
return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod,
annotationName, classValuesAsString, false);
}
}
```
## StandardAnnotationMetadata
- StandardAnnotationMetadata是StandardClassMetadata的子类
- 还是一个基于JAVA 反射做的一个类
- 获取注解属性map
```java
@Override
@Nullable
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
if (this.nestedAnnotationsAsMap) {
return AnnotationMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString);
}
return AnnotatedElementUtils.getMergedAnnotationAttributes(
getIntrospectedClass(), annotationName, classValuesAsString, false);
}
```
- `org.springframework.core.annotation.AnnotatedElementUtils#getMergedAnnotationAttributes(java.lang.reflect.AnnotatedElement, java.lang.String, boolean, boolean)`
- `org.springframework.core.annotation.AnnotatedElementUtils#getAnnotationAttributes`
- `org.springframework.core.annotation.MergedAnnotation#asAnnotationAttributes`
```java
@Nullable
public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
MergedAnnotation<?> mergedAnnotation = getAnnotations(element)
.get(annotationName, null, MergedAnnotationSelectors.firstDirectlyDeclared());
return getAnnotationAttributes(mergedAnnotation, classValuesAsString, nestedAnnotationsAsMap);
}
```
- 查看这个方法的源码借助测试类`org.springframework.core.annotation.AnnotatedElementUtilsTests#getMergedAnnotationAttributesOnClassWithLocalAnnotation`
- getAnnotations() 方法
### getAnnotations
- `org.springframework.core.annotation.MergedAnnotations#from(java.lang.reflect.AnnotatedElement, org.springframework.core.annotation.MergedAnnotations.SearchStrategy, org.springframework.core.annotation.RepeatableContainers)`
- `org.springframework.core.annotation.TypeMappedAnnotations#from(java.lang.reflect.AnnotatedElement, org.springframework.core.annotation.MergedAnnotations.SearchStrategy, org.springframework.core.annotation.RepeatableContainers, org.springframework.core.annotation.AnnotationFilter)`
- 最终我们找到的代码如下
```java
static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy,
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
if (AnnotationsScanner.isKnownEmpty(element, searchStrategy)) {
return NONE;
}
return new TypeMappedAnnotations(element, searchStrategy, repeatableContainers, annotationFilter);
}
```
- 判断是否为空. 为空返回None不会为空构造出一个对象org.springframework.core.annotation.TypeMappedAnnotations
### MergedAnnotations
```java
public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>> {
//确定注解是否存在
<A extends Annotation> boolean isPresent(Class<A> annotationType);
//注解是否直接存在
<A extends Annotation> boolean isDirectlyPresent(Class<A> annotationType);
// 获取匹配的注解
<A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType);
// 省略其他
}
```
- 这个接口中还有两个方法
1. `of`
将多个`MergedAnnotations`合并
2. `from`
将多个注解合并
### SearchStrategy
```java
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. This strategy
* is only really useful when used with {@link Class} types since the
* {@link Inherited @Inherited} annotation is ignored for all other
* {@linkplain AnnotatedElement annotated elements}. This strategy does
* not search implemented interfaces.
*
* 继承查找
*/
INHERITED_ANNOTATIONS,
/**
* Find all directly declared and superclass annotations. This strategy
* is similar to {@link #INHERITED_ANNOTATIONS} except the annotations
* do not need to be meta-annotated with {@link Inherited @Inherited}.
* This strategy does not search implemented interfaces.
* 查找当前类和父类的注解
*/
SUPERCLASS,
/**
* Perform a full search of the entire type hierarchy, including
* superclasses and implemented interfaces. 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. This strategy is similar to
* {@link #TYPE_HIERARCHY} except that {@linkplain Class#getEnclosingClass()
* enclosing classes} are also searched. Superclass annotations do not
* need to be meta-annotated with {@link Inherited @Inherited}. When
* searching a {@link Method} source, this strategy is identical to
* {@link #TYPE_HIERARCHY}.
*/
TYPE_HIERARCHY_AND_ENCLOSING_CLASSES
}
```
- `org.springframework.core.annotation.TypeMappedAnnotations#get(java.lang.String, java.util.function.Predicate<? super org.springframework.core.annotation.MergedAnnotation<A>>, org.springframework.core.annotation.MergedAnnotationSelector<A>)`
```java
@Override
public <A extends Annotation> MergedAnnotation<A> get(String annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector) {
// 匹配校验
if (this.annotationFilter.matches(annotationType)) {
return MergedAnnotation.missing();
}
MergedAnnotation<A> result = scan(annotationType,
new MergedAnnotationFinder<>(annotationType, predicate, selector));
return (result != null ? result : MergedAnnotation.missing());
}
```
#### Scan
`org.springframework.core.annotation.AnnotationsScanner#scan(C, java.lang.reflect.AnnotatedElement, org.springframework.core.annotation.MergedAnnotations.SearchStrategy, org.springframework.core.annotation.AnnotationsProcessor<C,R>, java.util.function.BiPredicate<C,java.lang.Class<?>>)`
```java
@Nullable
static <C, R> R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy,
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
R result = process(context, source, searchStrategy, processor, classFilter);
return processor.finish(result);
}
```
在这个里面重点关注`PROCESS`方法
```java
@Nullable
private static <C, R> R process(C context, AnnotatedElement source,
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor,
@Nullable BiPredicate<C, Class<?>> classFilter) {
if (source instanceof Class) {
return processClass(context, (Class<?>) source, searchStrategy, processor, classFilter);
}
if (source instanceof Method) {
return processMethod(context, (Method) source, searchStrategy, processor, classFilter);
}
return processElement(context, source, processor, classFilter);
}
```
测试类
```java
@Transactional("TxConfig")
static class TxConfig {
}
```
显然这是一个类他会走`processClass`方法
- 根据扫描方式进行扫描
```java
@Nullable
private static <C, R> R processClass(C context, Class<?> source,
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor,
@Nullable BiPredicate<C, Class<?>> classFilter) {
switch (searchStrategy) {
case DIRECT:
return processElement(context, source, processor, classFilter);
case INHERITED_ANNOTATIONS:
return processClassInheritedAnnotations(context, source, searchStrategy, processor, classFilter);
case SUPERCLASS:
return processClassHierarchy(context, source, processor, classFilter, false, false);
case TYPE_HIERARCHY:
return processClassHierarchy(context, source, processor, classFilter, true, false);
case TYPE_HIERARCHY_AND_ENCLOSING_CLASSES:
return processClassHierarchy(context, source, processor, classFilter, true, true);
}
throw new IllegalStateException("Unsupported search strategy " + searchStrategy);
}
```
- 扫描的形式就不贴出完整代码了
`finish`就包装一下返回.
- 此时`org.springframework.core.annotation.AnnotatedElementUtils#getMergedAnnotationAttributes(java.lang.reflect.AnnotatedElement, java.lang.String, boolean, boolean)`这个方法走到了最后一步`org.springframework.core.annotation.AnnotatedElementUtils#getAnnotationAttributes`
- 最后的组装map方法
`org.springframework.core.annotation.TypeMappedAnnotation#asMap(java.util.function.Function<org.springframework.core.annotation.MergedAnnotation<?>,T>, org.springframework.core.annotation.MergedAnnotation.Adapt...)`
```java
@Override
public AnnotationAttributes asAnnotationAttributes(Adapt... adaptations) {
return asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType()), adaptations);
}
```
```java
@Override
public <T extends Map<String, Object>> T asMap(Function<MergedAnnotation<?>, T> factory, Adapt... adaptations) {
T map = factory.apply(this);
Assert.state(map != null, "Factory used to create MergedAnnotation Map must not return null");
AttributeMethods attributes = this.mapping.getAttributes();
for (int i = 0; i < attributes.size(); i++) {
Method attribute = attributes.get(i);
Object value = (isFiltered(attribute.getName()) ? null :
getValue(i, getTypeForMapOptions(attribute, adaptations)));
if (value != null) {
map.put(attribute.getName(),
adaptValueForMapOptions(attribute, value, map.getClass(), factory, adaptations));
}
}
return map;
}
```
- 获取属性列表,循环, 放入map 返回.
map
key: 注解的函数
value: 函数对应的值
```java
@Transactional("TxConfig")
```
```java
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Inherited
@interface Transactional {
String value() default "";
String qualifier() default "transactionManager";
boolean readOnly() default false;
}
```
如果是上面这样的结构那么返回值为
```json
value:TxConfig
qulifiter:transactionManager
readOnlay:false
```
![image-20200824104529315](/images/spring/image-20200824104529315.png)
## SimpleMetadataReader
- 构造方法传递三个参数直接使用
```java
final class SimpleMetadataReader implements MetadataReader {
private static final int PARSING_OPTIONS = ClassReader.SKIP_DEBUG
| ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES;
private final Resource resource;
private final AnnotationMetadata annotationMetadata;
SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader);
getClassReader(resource).accept(visitor, PARSING_OPTIONS);
this.resource = resource;
this.annotationMetadata = visitor.getMetadata();
}
private static ClassReader getClassReader(Resource resource) throws IOException {
try (InputStream is = new BufferedInputStream(resource.getInputStream())) {
try {
return new ClassReader(is);
}
catch (IllegalArgumentException ex) {
throw new NestedIOException("ASM ClassReader failed to parse class file - " +
"probably due to a new Java class file version that isn't supported yet: " + resource, ex);
}
}
}
@Override
public Resource getResource() {
return this.resource;
}
@Override
public ClassMetadata getClassMetadata() {
return this.annotationMetadata;
}
@Override
public AnnotationMetadata getAnnotationMetadata() {
return this.annotationMetadata;
}
}
```
## SimpleMetadataReaderFactory
- 关注点为如何获取`MetadataReader`
1. 通过资源直接new出来
2. 通过className转换成资源地址,
3. 将资源地址转换成`Resource`对象
4. new出来
```java
@Override
public MetadataReader getMetadataReader(String className) throws IOException {
try {
String resourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(className) + ClassUtils.CLASS_FILE_SUFFIX;
Resource resource = this.resourceLoader.getResource(resourcePath);
return getMetadataReader(resource);
}
catch (FileNotFoundException ex) {
// Maybe an inner class name using the dot name syntax? Need to use the dollar syntax here...
// ClassUtils.forName has an equivalent check for resolution into Class references later on.
int lastDotIndex = className.lastIndexOf('.');
if (lastDotIndex != -1) {
String innerClassName =
className.substring(0, lastDotIndex) + '$' + className.substring(lastDotIndex + 1);
String innerClassResourcePath = ResourceLoader.CLASSPATH_URL_PREFIX +
ClassUtils.convertClassNameToResourcePath(innerClassName) + ClassUtils.CLASS_FILE_SUFFIX;
Resource innerClassResource = this.resourceLoader.getResource(innerClassResourcePath);
if (innerClassResource.exists()) {
return getMetadataReader(innerClassResource);
}
}
throw ex;
}
}
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
```