Spring元数据Metadata的使用,注解编程之AnnotationMetadata,ClassMetadata、MetadataReaderFactory【享学Spring】(上)

简介: Spring元数据Metadata的使用,注解编程之AnnotationMetadata,ClassMetadata、MetadataReaderFactory【享学Spring】(上)

前言


Spring在2.0的时候就支持了基于XML Schema的扩展机制,让我们可以自定义的对xml配置文件进行扩展(四大步骤,有兴趣的可以自己学习),比如鼎鼎大名的Dubbo它就扩展了xml,用它来引入服务或者导出服务。

随着Spring3.0+的发展,xml慢慢的淡出了我们的视野,特别是Spring Boot的流行让xml彻底消失,所有的xml配置都使用注解的方式进行了代替。有的人说注解编程源码难度是 XML 扩展好几倍,其实我并不这么认为,本文就着眼于大多数小伙伴比较费解的元数据(Metadata)进行分析,给深入理解注解编程铺路。


元数据


元数据:数据的数据。比如Class就是一种元数据。Metadata在org.springframework.core.type包名下,还有用于读取的子包classreading也是重要知识点。此体系大致的类结构列出如下图:


image.png


image.png


可以看到顶层接口有两个:ClassMetadata和AnnotatedTypeMetadata


注解上的注解,Spring将其定义为元注解(meta-annotation),如 @Component标注在 @Service上,@Component就被称作为元注解。后面我们就将注解的注解称为元注解。


ClassMetadata:对Class的抽象和适配


此接口的所有方法,基本上都跟Class有关。

// @since 2.5
public interface ClassMetadata {
  // 返回类名(注意返回的是最原始的那个className)
  String getClassName();
  boolean isInterface();
  // 是否是注解
  boolean isAnnotation();
  boolean isAbstract();
  // 是否允许创建  不是接口且不是抽象类  这里就返回true了
  boolean isConcrete();
  boolean isFinal();
  // 是否是独立的(能够创建对象的)  比如是Class、或者内部类、静态内部类
  boolean isIndependent();
  // 是否有内部类之类的东东
  boolean hasEnclosingClass();
  @Nullable
  String getEnclosingClassName();
  boolean hasSuperClass();
  @Nullable
  String getSuperClassName();
  // 会把实现的所有接口名称都返回  具体依赖于Class#getSuperclass
  String[] getInterfaceNames();
  // 基于:Class#getDeclaredClasses  返回类中定义的公共、私有、保护的内部类
  String[] getMemberClassNames();
}

它的继承树如下:


image.png


StandardClassMetadata


基于Java标准的(Standard)反射实现元数据的获取。


// @since 2.5
public class StandardClassMetadata implements ClassMetadata {
  // 用于内省的Class类
  private final Class<?> introspectedClass;
  // 唯一构造函数:传进来的Class,作为内部的内省对象
  public StandardClassMetadata(Class<?> introspectedClass) {
    Assert.notNull(introspectedClass, "Class must not be null");
    this.introspectedClass = introspectedClass;
  }
  ... // 后面所有的方法实现,都是基于introspectedClass,类似代理模式。举例如下:
  public final Class<?> getIntrospectedClass() {
    return this.introspectedClass;
  }
  @Override
  public boolean isInterface() {
    return this.introspectedClass.isInterface();
  }
  @Override
  public String[] getMemberClassNames() {
    LinkedHashSet<String> memberClassNames = new LinkedHashSet<>(4);
    for (Class<?> nestedClass : this.introspectedClass.getDeclaredClasses()) {
      memberClassNames.add(nestedClass.getName());
    }
    return StringUtils.toStringArray(memberClassNames);
  }
}


它有个非常重要的子类:StandardAnnotationMetadata它和注解密切相关,在文章下半部分重点分析。


MethodsMetadata:新增访问方法元数据的接口


它是子接口,主要增加了从Class里获取到MethodMetadata们的方法:


// @since 2.1 可以看到它出现得更早一些
public interface MethodsMetadata extends ClassMetadata {
  // 返回该class所有的方法
  Set<MethodMetadata> getMethods();
  // 方法指定方法名的方法们(因为有重载嘛~)
  Set<MethodMetadata> getMethods(String name);
}


名字上请不要和MethodMetadata搞混了,MethodMetadata是AnnotatedTypeMetadata的子接口,代表具体某一个Type(方法上的注解);而此类是个ClassMetadata,它能获取到本类里所有的方法Method(MethodMetadata)~

AnnotatedTypeMetadata:对注解元素的封装适配


什么叫注解元素(AnnotatedElement)?比如我们常见的Class、Method、Constructor、Parameter等等都属于它的子类都属于注解元素。简单理解:只要能在上面标注注解都属于这种元素。Spring4.0新增的这个接口提供了对注解统一的、便捷的访问,使用起来更加的方便高效了。

// @since 4.0
public interface AnnotatedTypeMetadata {
  // 此元素是否标注有此注解~~~~
  // annotationName:注解全类名
  boolean isAnnotated(String annotationName);
  // 这个就厉害了:取得指定类型注解的所有的属性 - 值(k-v)
  // annotationName:注解全类名
  // classValuesAsString:若是true表示 Class用它的字符串的全类名来表示。这样可以避免Class被提前加载
  @Nullable
  Map<String, Object> getAnnotationAttributes(String annotationName);
  @Nullable
  Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);
  // 参见这个方法的含义:AnnotatedElementUtils.getAllAnnotationAttributes
  @Nullable
  MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);
  @Nullable
  MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
}


它的继承树如下:


image.png



两个子接口相应的都提供了标准实现以及基于ASM的Visitor模式实现。


ASM 是一个通用的 Java 字节码操作和分析框架。它可以用于修改现有类或直接以二进制形式动态生成类。 ASM 虽然提供与其他 Java 字节码框架如 Javassist,CGLIB类似的功能,但是其设计与实现小而快,且性能足够高。


Spring 直接将 ASM 框架核心源码内嵌于 Spring-core中,目前`Spring 5.1使用ASM 7 版本。

相关文章
|
2月前
|
Java 开发者 Spring
【SpringBoot 异步魔法】@Async 注解:揭秘 SpringBoot 中异步方法的终极奥秘!
【8月更文挑战第25天】异步编程对于提升软件应用的性能至关重要,尤其是在高并发环境下。Spring Boot 通过 `@Async` 注解简化了异步方法的实现。本文详细介绍了 `@Async` 的基本用法及配置步骤,并提供了示例代码展示如何在 Spring Boot 项目中创建与管理异步任务,包括自定义线程池、使用 `CompletableFuture` 处理结果及异常情况,帮助开发者更好地理解和运用这一关键特性。
125 1
|
2月前
|
缓存 Java 数据库连接
Spring Boot奇迹时刻:@PostConstruct注解如何成为应用初始化的关键先生?
【8月更文挑战第29天】作为一名Java开发工程师,我一直对Spring Boot的便捷性和灵活性着迷。本文将深入探讨@PostConstruct注解在Spring Boot中的应用场景,展示其在资源加载、数据初始化及第三方库初始化等方面的作用。
53 0
|
7天前
|
Java Spring 容器
Spring使用异步注解@Async正确姿势
Spring使用异步注解@Async正确姿势,异步任务,spring boot
|
7天前
|
XML Java 数据格式
spring复习03,注解配置管理bean
Spring框架中使用注解配置管理bean的方法,包括常用注解的标识组件、扫描组件、基于注解的自动装配以及使用注解后的注意事项,并提供了一个基于注解自动装配的完整示例。
spring复习03,注解配置管理bean
|
7天前
|
XML 前端开发 Java
控制spring框架注解介绍
控制spring框架注解介绍
|
20天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
2月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
38 0
|
2月前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
35 0
|
2月前
|
Java Spring 供应链
Spring 框架事件发布与监听机制,如魔法风暴席卷软件世界,开启奇幻编程之旅!
【8月更文挑战第31天】《Spring框架中的事件发布与监听机制》介绍了Spring中如何利用事件发布与监听机制实现组件间的高效协作。这一机制像城市中的广播系统,事件发布者发送消息,监听器接收并响应。通过简单的示例代码,文章详细讲解了如何定义事件类、创建事件发布者与监听器,并确保组件间松散耦合,提升系统的可维护性和扩展性。掌握这一机制,如同拥有一把开启高效软件开发大门的钥匙。
39 0
|
2月前
|
监控 安全 Java
【开发者必备】Spring Boot中自定义注解与处理器的神奇魔力:一键解锁代码新高度!
【8月更文挑战第29天】本文介绍如何在Spring Boot中利用自定义注解与处理器增强应用功能。通过定义如`@CustomProcessor`注解并结合`BeanPostProcessor`实现特定逻辑处理,如业务逻辑封装、配置管理及元数据分析等,从而提升代码整洁度与可维护性。文章详细展示了从注解定义、处理器编写到实际应用的具体步骤,并提供了实战案例,帮助开发者更好地理解和运用这一强大特性,以实现代码的高效组织与优化。
56 0
下一篇
无影云桌面