货架网站开发,wordpress 汽车租赁,服装鞋帽 网站建设,Wordpress会员插件出错点击上方“匠心零度”#xff0c;选择“设为星标”做积极的人#xff0c;而不是积极废人来源#xff1a;my.oschina.net/floor/blog/4325651前言1.Component解析流程找入口找核心方法概要分析2.查文档找思路3. 探寻Component派生性流程1. 确定metadataReader2.查看match方法… 点击上方“匠心零度”选择“设为星标”做积极的人而不是积极废人来源my.oschina.net/floor/blog/4325651前言1.Component解析流程找入口找核心方法概要分析2.查文档找思路3. 探寻Component派生性流程1. 确定metadataReader2.查看match方法找重点方法逐步分析总结前言Component和Service都是工作中常用的注解Spring如何解析1.Component解析流程找入口Spring Framework2.0开始引入可扩展的XML编程机制该机制要求XML Schema命名空间需要与Handler建立映射关系。该关系配置在相对于classpath下的/META-INF/spring.handlers中。如上图所示 ContextNamespaceHandler对应context:... 分析的入口。找核心方法浏览ContextNamespaceHandler在parse中有一个很重要的注释// Actually scan for bean definitions and register them.ClassPathBeanDefinitionScanner scanner configureScanner(parserContext, element);大意是ClassPathBeanDefinitionScanner#doScan是扫描BeanDefinition并注册的实现 。ClassPathBeanDefinitionScanner 的源码如下protected Set doScan(String... basePackages) { Assert.notEmpty(basePackages, At least one base package must be specified); Set beanDefinitions new LinkedHashSet();for (String basePackage : basePackages) {//findCandidateComponents 读资源装换为BeanDefinition Set candidates findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName this.beanNameGenerator.generateBeanName(candidate, this.registry);if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); }if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); }if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder new BeanDefinitionHolder(candidate, beanName); definitionHolder AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } }return beanDefinitions;}上边的代码从方法名猜测findCandidateComponents从classPath扫描组件并转换为备选BeanDefinition也就是要做的解析Component的核心方法。概要分析findCandidateComponents在其父类ClassPathScanningCandidateComponentProvider 中。public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {//省略其他代码public Set findCandidateComponents(String basePackage) { if (this.componentsIndex ! null indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); }}private Set scanCandidateComponents(String basePackage) { Set candidates new LinkedHashSet();try { String packageSearchPath ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX resolveBasePackage(basePackage) / this.resourcePattern; Resource[] resources getResourcePatternResolver().getResources(packageSearchPath);//省略部分代码for (Resource resource : resources) {//省略部分代码if (resource.isReadable()) {try { MetadataReader metadataReader getMetadataReaderFactory().getMetadataReader(resource);if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(resource);if (isCandidateComponent(sbd)) { candidates.add(sbd);//省略部分代码 } }catch (IOException ex) {//省略部分代码 }return candidates;}}findCandidateComponents大体思路如下String packageSearchPath ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX resolveBasePackage(basePackage) / this.resourcePattern; 将package转化为ClassLoader类资源搜索路径packageSearchPath例如com.wl.spring.boot转化为classpath*:com/wl/spring/boot/**/*.classResource[] resources getResourcePatternResolver().getResources(packageSearchPath); 加载搜素路径下的资源。isCandidateComponent 判断是否是备选组件candidates.add(sbd); 添加到返回结果的listClassPathScanningCandidateComponentProvider#isCandidateComponent其源码如下protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { //省略部分代码 for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false;}includeFilters由registerDefaultFilters()设置初始值有Component没有Service啊protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter( ((Class extends Annotation) ClassUtils.forName(javax.annotation.ManagedBean, cl)), false)); logger.trace(JSR-250 javax.annotation.ManagedBean found and supported for component scanning); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { this.includeFilters.add(new AnnotationTypeFilter( ((Class extends Annotation) ClassUtils.forName(javax.inject.Named, cl)), false)); logger.trace(JSR-330 javax.inject.Named annotation found and supported for component scanning); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. }}Spring如何处理Service的注解的呢2.查文档找思路查阅官方文档下面这话https://docs.spring.io/spring/docs/5.0.17.RELEASE/spring-framework-reference/core.html#beans-meta-annotationsComponent is a generic stereotype for any Spring-managed component. Repository, Service, and Controller are specializations of Component大意如下Component是任何Spring管理的组件的通用原型。Repository、Service和Controller是派生自Component。Target({ElementType.TYPE})Retention(RetentionPolicy.RUNTIME)Documented// Service 派生自ComponentComponentpublic interface Service { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * return the suggested component name, if any (or empty String otherwise) */ AliasFor(annotation Component.class) String value() default ;}Component是Service的元注解Spring 大概率在读取Service也读取了它的元注解并将Service作为Component处理。3. 探寻Component派生性流程回顾ClassPathScanningCandidateComponentProvider 中的关键的代码片段如下private Set scanCandidateComponents(String basePackage) { //省略其他代码 MetadataReader metadataReader getMetadataReaderFactory().getMetadataReader(resource); if(isCandidateComponent(metadataReader)){ //.... }}public final MetadataReaderFactory getMetadataReaderFactory() { if (this.metadataReaderFactory null) { this.metadataReaderFactory new CachingMetadataReaderFactory(); } return this.metadataReaderFactory;}1. 确定metadataReaderCachingMetadataReaderFactory继承自 SimpleMetadataReaderFactory就是对SimpleMetadataReaderFactory加了一层缓存。其内部的SimpleMetadataReaderFactory#getMetadataReader 为public class SimpleMetadataReaderFactory implements MetadataReaderFactory { Overridepublic MetadataReader getMetadataReader(Resource resource) throws IOException { return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());} }这里可以看出MetadataReader metadataReader new SimpleMetadataReader(...);2.查看match方法找重点方法AnnotationTypeFilter#matchself方法如下Overrideprotected boolean matchSelf(MetadataReader metadataReader) { AnnotationMetadata metadata metadataReader.getAnnotationMetadata(); return metadata.hasAnnotation(this.annotationType.getName()) || (this.considerMetaAnnotations metadata.hasMetaAnnotation(this.annotationType.getName()));}是metadata.hasMetaAnnotation法从名称看是处理元注解我们重点关注逐步分析找metadata.hasMetaAnnotationmetadatametadataReader.getAnnotationMetadata();metadataReader new SimpleMetadataReader(...)metadata new SimpleMetadataReader#getAnnotationMetadata()//SimpleMetadataReader 的构造方法SimpleMetadataReader(Resource resource, Nullable ClassLoader classLoader) throws IOException { InputStream is new BufferedInputStream(resource.getInputStream()); ClassReader classReader; try { classReader new ClassReader(is); } catch (IllegalArgumentException ex) { throw new NestedIOException(ASM ClassReader failed to parse class file - probably due to a new Java class file version that isnt supported yet: resource, ex); } finally { is.close(); } AnnotationMetadataReadingVisitor visitor new AnnotationMetadataReadingVisitor(classLoader); classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata visitor; // (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor) this.classMetadata visitor; this.resource resource;}metadatanew SimpleMetadataReader(...)**.**getAnnotationMetadata() new AnnotationMetadataReadingVisitor(。。)也就是说metadata.hasMetaAnnotationAnnotationMetadataReadingVisitor#hasMetaAnnotation其方法如下public class AnnotationMetadataReadingVisitor{ // 省略部分代码Overridepublic boolean hasMetaAnnotation(String metaAnnotationType) { Collection allMetaTypes this.metaAnnotationMap.values();for (Set metaTypes : allMetaTypes) {if (metaTypes.contains(metaAnnotationType)) {return true; } }return false;}}逻辑很简单就是判断该注解的元注解在在不在metaAnnotationMap中如果在就返回true。这里面核心就是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这里的annotationVisitorAnnotationMetadataReadingVisitor#visitAnnotation源码如下注意这里传递了metaAnnotationMappublic class AnnotationMetadataReadingVisitor{Overridepublic 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);}}annotationVisitorAnnotationAttributesReadingVisitor查阅annotationVisitor.visitEnd()annotationVisitorAnnotationAttributesReadingVisitor#visitEnd()public class AnnotationAttributesReadingVisitor{Overridepublic void visitEnd() { super.visitEnd(); Class extends Annotation 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#findCandidateComponents1、将package转化为ClassLoader类资源搜索路径packageSearchPath2、加载搜素路径下的资源。3、isCandidateComponent 判断是否是备选组件。内部调用的TypeFilter的match方法AnnotationTypeFilter#matchself中metadata.hasMetaAnnotation处理元注解metadata.hasMetaAnnotationAnnotationMetadataReadingVisitor#hasMetaAnnotation就是判断当前注解的元注解在不在metaAnnotationMap中。AnnotationAttributesReadingVisitor#visitEnd()内部方法recursivelyCollectMetaAnnotations 递归的读取注解与注解的元注解(读Service再读元注解Component)并设置到metaAnnotationMap4、添加到返回结果的listEND如果读完觉得有收获的话欢迎点【好看】关注【匠心零度】查阅更多精彩历史让我“好看”