1 Star 0 Fork 156

liuRuiXi / Spring-Analysis

forked from huifer / Code-Analysis 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
第二十五章-类元数据.md 7.34 KB
一键复制 编辑 原始数据 按行查看 历史
huifer 提交于 2021-02-18 16:46 . fix: 修改图片地址

第二十五章 类元数据

本章笔者将围绕 org.springframework.core.type.ClassMetadata 接口和各位读者一起探讨它做了什么。

25.1 接口说明

首先我们来看 ClassMetadata 接口中定义了那些方法

public interface ClassMetadata {

    /**
     * 类名
     */
    String getClassName();

    /**
     * 是否是接口
     */
    boolean isInterface();

    /**
     * 是否是注解
     */
    boolean isAnnotation();

    /**
     * 是否是超类
     */
    boolean isAbstract();

    /**
     * 是否允许创建,实例化
     */
    default boolean isConcrete() {
        return !(isInterface() || isAbstract());
    }

    /**
     * 是否有final修饰
     */
    boolean isFinal();

    /**
     * 是否独立
     * 1. 不是内部类
     * 2. 不是继承类
     */
    boolean isIndependent();

 
    default boolean hasEnclosingClass() {
        return (getEnclosingClassName() != null);
    }

  
    @Nullable
    String getEnclosingClassName();

    /**
     * 是否有父类
     */
    default boolean hasSuperClass() {
        return (getSuperClassName() != null);
    }

    /**
     * 父类名称
     */
    @Nullable
    String getSuperClassName();

    /**
     * 实现接口列表
     */
    String[] getInterfaceNames();

    /**
     * 成员列表
     */
    String[] getMemberClassNames();

}
方法名称 方法返回值 说明
getClassName String 获取类名称
isInterface boolean 判断是否是接口
isAnnotation boolean 判断是否是注解
isAbstract boolean 判断是否 abstract 修饰
isConcrete boolean 是否允许实例化
isFinal boolean 是否是 final 修饰
isIndependent boolean 是否是一个独立类
hasEnclosingClass boolean 是否存在封闭类类名
getEnclosingClassName String 获取封闭类类名
hasSuperClass boolean 是否存在父类
getSuperClassName String 获取父类名称
getInterfaceNames String[] 获取实现的接口名称
getMemberClassNames String[] 获取内部类名称

在这个这段代码中笔者对 getEnclosingClassName 做一个简单的例子

public class ClassMetaTest {
   @Test
   void testEnclosingClassName() {
      Class<A> aClass = A.class;
      Class<?> enclosingClass = aClass.getEnclosingClass();
      System.out.println(enclosingClass);

      Class<B> bClass = B.class;
      Class<?> enclosingClass1 = bClass.getEnclosingClass();
      System.out.println(enclosingClass1);

   }

   public static class B {

   }

   public class A {

   }
}
  • 输出结果
class com.source.hot.ioc.book.ioc.ClassMetaTest
class com.source.hot.ioc.book.ioc.ClassMetaTest

如果我们将一个类完全脱离放在包下面单独使用,然后我们再看输出结果是什么。

package com.source.hot.ioc.book.ioc;

public class CTest {
}

测试方法

@Test
void testCtest(){
   System.out.println(CTest.class.getEnclosingClass());
}
  • 输出结果
null

现在我们可以这样理解 getEnclosingClass 的内容了,如果当前类是一个内部类那么这个方法的执行结果将是当前类包裹住的类。

下面我们来看 Spring 中对其的实现,来看类图

ClassMetadata

25.2 StandardClassMetadata分析

下面我们来看 Spring 中的处理类 StandardClassMetadata,在这个处理类中使用的是 JDK Class 对象的内容,基本操作都是由 Class 提供,这个类对我们学习反射比较有帮助。

首先来看构造方法

@Deprecated
public StandardClassMetadata(Class<?> introspectedClass) {
    Assert.notNull(introspectedClass, "Class must not be null");
    this.introspectedClass = introspectedClass;
}

这个构造方法传递了一个 Class 对象,这个参数在整个方法实现中承担了所有的功能提供者,比如 getClassName 的实现、

  • StandardClassMetadata#getClassName 方法详情
@Override
public String getClassName() {
    return this.introspectedClass.getName();
}

StandardClassMetadata 的实现过程中大量的采用了 Class 所提供的方法各位可以查看下面代码来对整个 StandardClassMetadata 类有所了解

public class StandardClassMetadata implements ClassMetadata {

    /**
     * 被解析的类对象
     */
    private final Class<?> introspectedClass;


    /**
     * Create a new StandardClassMetadata wrapper for the given Class.
     * 构造函数
     * @param introspectedClass the Class to introspect
     * @deprecated since 5.2 in favor of {@link StandardAnnotationMetadata}
     */
    @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() {
       // 是否存在内部类
      // 是否有 class
      // 是否有 static 修饰
      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);
    }

}
Java
1
https://gitee.com/liuruixi/spring-analysis.git
git@gitee.com:liuruixi/spring-analysis.git
liuruixi
spring-analysis
Spring-Analysis
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891