背景
在工作3年以上的时候,在写业务代码的时候我们经常会自定义一些注解用于用于简化代码的开发。一个比较实用的例子见 上一篇博客 。注解其实只是作为一个标识,而真正起作用的代码需要我们自己定义,但是前提是我们要找到这个注解,并解析这个注解的相关信息,我们可以使用jdk提供的类来做,但是它不够灵活,这篇文章介绍另一种方式,也是spring解析注解用的方式 MetadataReader
,它是spring提供的一个工具。
MetadataReader介绍
一、MetadataReader 的作用
MetadataReader表示类的元数据读取器。我们来看一下这个接口的功能
public interface MetadataReader {
/**
* Return the resource reference for the class file.
* 返回class文件的resource
*/
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();
}
它的默认实现类有
我们比较常用的类是 SimpleMetadataReader
。
二、创建MetadataReader
我们大致可以从接口中看到MetadataReader
的作用,那么在实际使用过程中该如何创建这个reader呢?
spring使用了工厂设计模式来创建,它提供了一些 MetadataReader
的工厂类,这些工厂类的作用见接口
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;
}
它的实现类有:
我们常使用的为 SimpleMetadataReaderFactory
。
final SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
final MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.interfaceJ.matedata.UserService");
final AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 如果这个类有方法上注解了 @EnableRoles,则创建动态代理
if (annotationMetadata.hasAnnotatedMethods(EnableRoles.class.getName())) {
for (MethodMetadata method : annotationMetadata.getAnnotatedMethods(EnableRoles.class.getName())) {
// 。。。创建动态代理
final Map<String, Object> attributes = method.getAnnotationAttributes(EnableRoles.class.getName