@Component,@Service等注解是如何被解析的? |
您所在的位置:网站首页 › @service注解 › @Component,@Service等注解是如何被解析的? |
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1、@Component解析流程找入口找核心方法概要分析 2、查文档找思路3.探寻@Component派生性流程确定metadataReader查看match方法找重点方法逐步分析找metadata.hasMetaAnnotation查找metaAnnotationMap赋值确定annotationVisitor查阅annotationVisitor.visitEnd() 总结 前言@Component和@Service都是工作中常用的注解,Spring如何解析? 提示:以下是本篇文章正文内容,下面案例可供参考 1、@Component解析流程 找入口Spring Framework2.0开始,引入可扩展的XML编程机制,该机制要求XML Schema命名空间需要与Handler建立映射关系。 该关系配置在相对于classpath下的/META-INF/spring.handlers中。 浏览ContextNamespaceHandler ClassPathBeanDefinitionScanner 的源码如下: findCandidateComponents:从classPath扫描组件,并转换为备选BeanDefinition,也就是要做的解析@Component的核心方法。 概要分析findCandidateComponents在其父类ClassPathScanningCandidateComponentProvider 中。 1.String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX resolveBasePackage(basePackage) + ‘/’ + this.resourcePattern; 将package转化为ClassLoader类资源 搜索路径packageSearchPath,例如:com.wl.spring.boot转化为classpath*:com/wl/spring/boot/**/*.class 2.Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); 加载搜素 路径下的资源。 3.isCandidateComponent 判断是否是备选组件 4.candidates.add(sbd); 添加到返回结果的list ClassPathScanningCandidateComponentProvider#isCandidateComponent其源码如下: 查阅官方文档,下面这话: https://docs.spring.io/spring/docs/5.0.17.RELEASE/spring-framework-reference/core.html#beans-meta-annotations
@Component是任何Spring管理的组件的通用原型。@Repository、@Service和@Controller是派生自@Component。
回顾ClassPathScanningCandidateComponentProvider 中的关键的代码片段如下: CachingMetadataReaderFactory继承自 SimpleMetadataReaderFactory,就是对SimpleMetadataReaderFactory加了一层缓存。 其内部的SimpleMetadataReaderFactory#getMetadataReader 为: MetadataReader metadataReader =new SimpleMetadataReader(…); 查看match方法找重点方法
metadata=metadataReader.getAnnotationMetadata(); metadataReader =new SimpleMetadataReader(…) metadata= new SimpleMetadataReader#getAnnotationMetadata() 也就是说 metadata.hasMetaAnnotation=AnnotationMetadataReadingVisitor#hasMetaAnnotation 其方法如下:
这里面核心就是metaAnnotationMap,搜索AnnotationMetadataReadingVisitor类,没有发现赋值的地方??!。 查找metaAnnotationMap赋值回到SimpleMetadataReader 的方法, //这个accept方法,很可疑,在赋值之前执行 SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException { //省略其他代码 AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader); classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata = visitor; }发现一个可疑的语句:classReader.accept。 查看accept方法 public class ClassReader { //省略其他代码 public void accept(..省略代码){ //省略其他代码 readElementValues( classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true), currentAnnotationOffset, true, charBuffer); } }查看readElementValues方法 public class ClassReader{ //省略其他代码 private int readElementValues( final AnnotationVisitor annotationVisitor, final int annotationOffset, final boolean named, final char[] charBuffer) { int currentOffset = annotationOffset; // Read the num_element_value_pairs field (or num_values field for an array_value). int numElementValuePairs = readUnsignedShort(currentOffset); currentOffset += 2; if (named) { // Parse the element_value_pairs array. while (numElementValuePairs-- > 0) { String elementName = readUTF8(currentOffset, charBuffer); currentOffset = readElementValue(annotationVisitor, currentOffset + 2, elementName, charBuffer); } } else { // Parse the array_value array. while (numElementValuePairs-- > 0) { currentOffset = readElementValue(annotationVisitor, currentOffset, /* named = */ null, charBuffer); } } if (annotationVisitor != null) { annotationVisitor.visitEnd(); } return currentOffset; } }这里面的核心就是 annotationVisitor.visitEnd(); 确定annotationVisitor这里的annotationVisitor=AnnotationMetadataReadingVisitor#visitAnnotation 源码如下,注意这里传递了metaAnnotationMap!! public class AnnotationMetadataReadingVisitor{ @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { String className = Type.getType(desc).getClassName(); this.annotationSet.add(className); return new AnnotationAttributesReadingVisitor( className, this.attributesMap, this.metaAnnotationMap, this.classLoader); } }annotationVisitor=AnnotationAttributesReadingVisitor 查阅annotationVisitor.visitEnd()annotationVisitor=AnnotationAttributesReadingVisitor#visitEnd() public class AnnotationAttributesReadingVisitor{ @Override public void visitEnd() { super.visitEnd(); Class annotationClass = this.attributes.annotationType(); if (annotationClass != null) { List attributeList = this.attributesMap.get(this.annotationType); if (attributeList == null) { this.attributesMap.add(this.annotationType, this.attributes); } else { attributeList.add(0, this.attributes); } if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) { try { Annotation[] metaAnnotations = annotationClass.getAnnotations(); if (!ObjectUtils.isEmpty(metaAnnotations)) { Set visited = new LinkedHashSet(); for (Annotation metaAnnotation : metaAnnotations) { recursivelyCollectMetaAnnotations(visited, metaAnnotation); } if (!visited.isEmpty()) { Set metaAnnotationTypeNames = new LinkedHashSet(visited.size()); for (Annotation ann : visited) { metaAnnotationTypeNames.add(ann.annotationType().getName()); } this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames); } } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to introspect meta-annotations on " + annotationClass + ": " + ex); } } } } } }内部方法recursivelyCollectMetaAnnotations 递归的读取注解,与注解的元注解(读@Service,再读元注解@Component),并设置到metaAnnotationMap,也就是AnnotationMetadataReadingVisitor 中的metaAnnotationMap中。 总结大致如下: ClassPathScanningCandidateComponentProvider#findCandidateComponents 1.将package转化为ClassLoader类资源搜索路径packageSearchPath 2.加载搜素路径下的资源。 3.isCandidateComponent 判断是否是备选组件。 内部调用的TypeFilter的match方法: AnnotationTypeFilter#matchself中metadata.hasMetaAnnotation处理元注解 metadata.hasMetaAnnotation=AnnotationMetadataReadingVisitor#hasMetaAnnotation 就是判断当前注解的元注解在不在metaAnnotationMap中。 AnnotationAttributesReadingVisitor#visitEnd()内部方法recursivelyCollectMetaAnnotations 递归的读 取注解,与注解的元注解(读@Service,再读元注解@Component),并设置到metaAnnotationMap4.添加到返回结果的list |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |