Spring源码导读之ClassMedata

  • Post author:
  • Post category:其他



Spring源码导读


目录


五种类型的Class


ClassMedata


AnnotationMetadataReadingVisitor


五种类型的Class

Class类种注释解释有五种类型的Class

用一个demo进行说明:

/**
 a) Top level classes  顶层类
 */
public class TopLevelClass {
    /**
     * c) Inner classes (non-static member classes) 非静态的成员类
     */
    class InnerClass {
    }

    /**
     * b) Nested classes (static member classes)  静态的成员类
     */
    static class NestedClass {
    }

    public static void main(String[] args) {
        /**
         * d) Local classes (named classes declared within a method) 局部类 申明在方法种的类
         */
        class LocalClass {
        }
        // e) Anonymous classes 匿名类
        Runnable runnable = new Runnable() {
            @Override
            public void run() {

            }
        };

        System.out.println("TopLevelClass的外围类是: " + (TopLevelClass.class.getEnclosingClass() == null ? null : TopLevelClass.class.getEnclosingClass().getSimpleName()));
        System.out.println("InnerClass的外围类是: " + InnerClass.class.getEnclosingClass().getSimpleName());
        System.out.println("NestedClass的外围类是: " + NestedClass.class.getEnclosingClass().getSimpleName());
        System.out.println("LocalClass的外围类是: " + LocalClass.class.getEnclosingClass().getSimpleName());
        System.out.println("AnonymousClass的外围类是: " + runnable.getClass().getEnclosingClass().getSimpleName());

        //memberClasses 包括Nested classes 和 Inner classes
        System.out.println("TopLevelClass声明的类有: " +  Arrays.stream(TopLevelClass.class.getDeclaredClasses()).map(Class::getSimpleName).collect(Collectors.toList()));
        System.out.println("NestedClass声明的类有: " + Arrays.stream( NestedClass.class.getDeclaredClasses()).map(Class::getSimpleName).collect(Collectors.toList()));

        System.out.println("声明TopLevelClass的类是: " + (TopLevelClass.class.getDeclaringClass() == null ? null : TopLevelClass.class.getDeclaringClass().getSimpleName()));
        System.out.println("声明NestedClass的类是" + NestedClass.class.getDeclaringClass().getSimpleName());
    }
}

运行结果:

ClassMedata

ClassMedata可以对一个隐含的类的对象进行封装,提供获取这个对象的类信息的一系列方法。



Spring对注解的增强

中我们看到一个类

StandardAnnotationMetadata

。它实现了ClassMetadata。在Spring注解模型中被广泛用到。

看下这个接口的实现。

public class StandardClassMetadata implements ClassMetadata {

	/**
	 * ClassMetadata可以对一个隐含的类进行管理, 提供对这个类的信息的获取机制
	 * introspected : 内省
	 */
	private final Class<?> introspectedClass;


	/**
	 * Create a new StandardClassMetadata wrapper for the given Class.
	 * @param introspectedClass the Class to introspect
	 */
	public StandardClassMetadata(Class<?> introspectedClass) {
		Assert.notNull(introspectedClass, "Class must not be null");
		this.introspectedClass = introspectedClass;
	}

	/**
	 * 获取这个隐含的类
	 */
	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 isConcrete() {
		return !(isInterface() || isAbstract());
	}
	/**
	 * 是不是final类,通过修饰符获取
	 */
	@Override
	public boolean isFinal() {
		return Modifier.isFinal(this.introspectedClass.getModifiers());
	}

	/**
	 * 是否是独立的类, (Top level classes 或者 Nested classes)
	 * !hasEnclosingClass() 没有外围类 =》Top level classes
	 * this.introspectedClass.getDeclaringClass() != null && Modifier.isStatic(this.introspectedClass.getModifiers() 被其他类申明, 且不是静态的 =》 Nested classes 
	 */
	@Override
	public boolean isIndependent() {
		return (!hasEnclosingClass() ||
				(this.introspectedClass.getDeclaringClass() != null &&
						Modifier.isStatic(this.introspectedClass.getModifiers())));
	}

	/**
	 * 是否有外围类
	 */	
	@Override
	public boolean hasEnclosingClass() {
		return (this.introspectedClass.getEnclosingClass() != null);
	}

	/**
	 * 获取其外围类
	 */	
	@Override
	@Nullable
	public String getEnclosingClassName() {
		Class<?> enclosingClass = this.introspectedClass.getEnclosingClass();
		return (enclosingClass != null ? enclosingClass.getName() : null);
	}
	/**
	 * 是否有超类
	 */	
	@Override
	public boolean hasSuperClass() {
		return (this.introspectedClass.getSuperclass() != 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);
	}

AnnotationMetadataReadingVisitor

StandardClassMetadata下面除了StandardAnnotationMetadata的实现,还有一个AnnotationMetadataReadingVisitor。

StandardAnnotationMetadata继承了StandardClassMetadata。他们对Class类型信息的获取用到是放射技术。性能较低,因此Spring也提供了AnnotationMetadataReadingVisitor,是通过对字节码的读取技术(ClassReader)获取类信息。

但是二者能做到的事情是一样。如果想了解这个AnnotationMetadataReadingVisitor,可以了解一下

字节码



版权声明:本文为lightj1996原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。