我们在之前的博客 Spring源码深度解析(郝佳)-学习-ASM 类字节码解析 简单的对字节码结构进行了分析,今天我们站在前面的基础上对Spring中类注解的读取,并创建BeanDefinition做更深层次的研究。
先上实例。
Car.java
@Component @Data public class Car { private String color = "red"; }
Dog.java
@Component public class Dog { }
MyRequestAnnotation.java
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Service public @interface MyRequestAnnotation { String value() default ""; }
MyTestAnnotation.java
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component @Mapping @MyRequestAnnotation public @interface MyTestAnnotation { String name() default ""; @AliasFor("path") String[] value() default {}; RequestMethod[] method() default {}; }
User.java
@Service("xxxx") @MyTestAnnotation("/user/info") public class User { @Autowired private Car car; }
spring35_resource_inject_1.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.spring_1_100.test_31_40.test35_resource_inject.anno"/> </beans>
测试:
public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_1_100/config_31_40/spring35_resource_inject_1.xml"); User user = (User) ac.getBean("xxxx"); }
关于前面资源的加载,以及命名空间的判断,这里不再做过多的缀述。这里直接做第三方标签的解析。
BeanDefinitionParserDelegate.java
public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); }
BeanDefinitionParserDelegate.java
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
DefaultNamespaceHandlerResolver.java
public NamespaceHandler resolve(String namespaceUri) { Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; try { Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); //调用处理器的init方法 namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "] not found", ex); } catch (LinkageError err) { throw new FatalBeanException("Invalid NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]: problem with handler class file or dependent class", err); } } }
在每个Spring包下META-INF中配置了spring.handlers,在里面配置了命名空间与处理器的对应关系:
http://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
,而http://www.springframework.org/schema/context 配置在在spring-context包下,这里调用ContextNamespaceHandler的init方法。
ContextNamespaceHandler.java
public class ContextNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); } }
因此,component-scan标签是在ComponentScanBeanDefinitionParser中解析的。再次回到parse方法。
NamespaceHandlerSupport.java
public BeanDefinition parse(Element element, ParserContext parserContext) { return findParserForElement(element, parserContext).parse(element, parserContext); }
NamespaceHandlerSupport.java
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); //从ContextNamespaceHandler的init方法中注册的标签和解析器之间的对应关系中获取解析器 BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser; }
ComponentScanBeanDefinitionParser.java
public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); // Actually scan for bean definitions and register them ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); // 真正的开始扫描解析 Set beanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
ClassPathBeanDefinitionScanner.java
protected Set doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); //创建bean定义的holder对象用于保存扫描后生成的bean定义对象 // 创建一个集合,存入扫描到的Bean 定义的封装类 Set beanDefinitions = new LinkedHashSet(); //循环我们的包路径集合 // 遍历扫描所给定的包 for (String basePackage : basePackages) { // 找到候选的 @Component // 调用父类的 ClassPathScanningCandidateComponentProvider 的 findCandidateComponents 方法 // 扫描给定类路径的,获取符合条件的Bean的定义 // 类路径的Bean定义扫描 ClassPathBeanDefinitionScanner 主要通过 findCandidateComponents() 方法调用其父类 ClassPathScanningCandidateComponentProvider // 来扫描获取给定包及其子包的类 Set candidates = findCandidateComponents(basePackage); // 遍历扫描得到的Bean for (BeanDefinition candidate : candidates) { // 获取Bean定义类中的@Scope注解的值,即获取Bean的作用域 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); // 为Bean设置注解配置的作用域 candidate.setScope(scopeMetadata.getScopeName()); //设置我们的beanName,为Bean生成名称 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); // 处理@AutoWired相关的 // 如果扫描到Bean不是Spring的注解Bean,则为Bean设置默认值 // 设置Bean的自动依赖注入装配属性等 if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } //处理jsr250相关的组件,如果扫描到的Bean是Spring的注解的Bean,则处理其通用的注解 if (candidate instanceof AnnotatedBeanDefinition) { // 处理注解Bean中通过的注解,在分析注解Bean定义类读取器时已经分析过了 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //把我们解析出来的组件bean定义注册到Spring IoC容器中,根据Bean名称检查指定的Bean是否需要在容器注册,或者是否是容器中 // 有冲突。 if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); // 根据注解中的配置的作用域,为Bean的应用的代理模式 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //注册到Spring IoC容器中,向容器注册扫描到的Bean registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
ClassPathScanningCandidateComponentProvider.java
public Set findCandidateComponents(String basePackage) { Set candidates = new LinkedHashSet(); try { //classpath*:com/spring_1_100/test_31_40/test35_resource_inject/anno/**/*.class 拼接获取资源的匹配表达式 String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + "/" + this.resourcePattern; //获取和表达式相匹配的所有的资源 Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); //遍历所有的资源 for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); //类是否有@Component注解,或者类中注解的祖先是不是有@Component注解 ,比如@Service注解上就配置了@Component if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
CachingMetadataReaderFactory.java
public MetadataReader getMetadataReader(Resource resource) throws IOException { if (getCacheLimit() <= 0) { return super.getMetadataReader(resource); } synchronized (this.metadataReaderCache) { MetadataReader metadataReader = this.metadataReaderCache.get(resource); if (metadataReader == null) { metadataReader = super.getMetadataReader(resource); this.metadataReaderCache.put(resource, metadataReader); } return metadataReader; } }
SimpleMetadataReaderFactory.java
public MetadataReader getMetadataReader(Resource resource) throws IOException { return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader()); }
SimpleMetadataReader.java
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException { InputStream is = new BufferedInputStream(resource.getInputStream()); ClassReader classReader; try { //在这里初始化类字节码常量池,在 Spring源码深度解析(郝佳)-学习-ASM 类字节码解析 中有详细的解析 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 isn't supported yet: " + resource, ex); } finally { is.close(); } AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader); classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata = visitor; this.classMetadata = visitor; this.resource = resource; }
因为accept方法里的篇幅过长,这里将不再做一一的解析,只是对其中比较关键的关于类,和属性的注解做分析了。
ClassReader.java
public void accept(final ClassVisitor classVisitor, final Attribute[] attrs, final int flags) { int u = header; // current offset in the class file char[] c = new char[maxStringLength];//UTF8字符串中最大长度 Context context = new Context(); context.attrs = attrs; context.flags = flags; context.buffer = c; //类的访问标识位,public ,private 等 int access = readUnsignedShort(u); String name = readClass(u + 2, c); String superClass = readClass(u + 4, c); String[] interfaces = new String[readUnsignedShort(u + 6)]; u += 8; for (int i = 0; i < interfaces.length; ++i) { interfaces[i] = readClass(u, c); u += 2; } //类的属性 String signature = null; String sourceFile = null; String sourceDebug = null; String enclosingOwner = null; String enclosingName = null; String enclosingDesc = null; int anns = 0; int ianns = 0; int tanns = 0; int itanns = 0; int innerClasses = 0; Attribute attributes = null; u = getAttributes(); for (int i = readUnsignedShort(u); i > 0; --i) { String attrName = readUTF8(u + 2, c); if ("SourceFile".equals(attrName)) { //获取源文件名称 sourceFile = readUTF8(u + 8, c); } else if ("InnerClasses".equals(attrName)) { innerClasses = u + 8; } else if ("EnclosingMethod".equals(attrName)) { enclosingOwner = readClass(u + 8, c); int item = readUnsignedShort(u + 10); if (item != 0) { enclosingName = readUTF8(items[item], c); enclosingDesc = readUTF8(items[item] + 2, c); } } else if (SIGNATURES && "Signature".equals(attrName)) { signature = readUTF8(u + 8, c); } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) { //类中配置了注解 anns = u + 8; } else if (ANNOTATIONS && "RuntimeVisibleTypeAnnotations".equals(attrName)) { tanns = u + 8; } else if ("Deprecated".equals(attrName)) { access |= Opcodes.ACC_DEPRECATED; } else if ("Synthetic".equals(attrName)) { access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; } else if ("SourceDebugExtension".equals(attrName)) { int len = readInt(u + 4); sourceDebug = readUTF(u + 8, len, new char[len]); } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) { ianns = u + 8; } else if (ANNOTATIONS && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { itanns = u + 8; } else if ("BootstrapMethods".equals(attrName)) { int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { bootstrapMethods[j] = v; v += 2 + readUnsignedShort(v + 2) << 1; } context.bootstrapMethods = bootstrapMethods; } else { Attribute attr = readAttribute(attrs, attrName, u + 8, readInt(u + 4), c, -1, null); if (attr != null) { attr.next = attributes; attributes = attr; } } u += 6 + readInt(u + 4); } //封装方法的基本属性 classVisitor.visit(readInt(items[1] - 7), access, name, signature, superClass, interfaces); // visits the source and debug info if ((flags & SKIP_DEBUG) == 0 && (sourceFile != null || sourceDebug != null)) { classVisitor.visitSource(sourceFile, sourceDebug); } // visits the outer class if (enclosingOwner != null) { classVisitor.visitOuterClass(enclosingOwner, enclosingName, enclosingDesc); } // visits the class annotations and type annotations if (ANNOTATIONS && anns != 0) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), true)); } } if (ANNOTATIONS && ianns != 0) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { v = readAnnotationValues(v + 2, c, true, classVisitor.visitAnnotation(readUTF8(v, c), false)); } } if (ANNOTATIONS && tanns != 0) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, classVisitor.visitTypeAnnotation(context.typeRef, context.typePath, readUTF8(v, c), true)); } } if (ANNOTATIONS && itanns != 0) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { v = readAnnotationTarget(context, v); v = readAnnotationValues(v + 2, c, true, classVisitor.visitTypeAnnotation(context.typeRef, context.typePath, readUTF8(v, c), false)); } } // visits the attributes while (attributes != null) { Attribute attr = attributes.next; attributes.next = null; classVisitor.visitAttribute(attributes); attributes = attr; } // visits the inner classes if (innerClasses != 0) { int v = innerClasses + 2; for (int i = readUnsignedShort(innerClasses); i > 0; --i) { classVisitor.visitInnerClass(readClass(v, c), readClass(v + 2, c), readUTF8(v + 4, c), readUnsignedShort(v + 6)); v += 8; } } // visits the fields and methods u = header + 10 + 2 * interfaces.length; for (int i = readUnsignedShort(u - 2); i > 0; --i) { u = readField(classVisitor, context, u); } u += 2; for (int i = readUnsignedShort(u - 2); i > 0; --i) { u = readMethod(classVisitor, context, u); } // visits the end of the class classVisitor.visitEnd(); }
AnnotationMetadataReadingVisitor.java
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { //从常量池中获取类注解的名字,比如常量池中Lorg/springframework/stereotype/Component; //是这样的一个字符串,前面的L表示当前是一对象,而后面的;也去掉,因此得到 // 当前注解的名字是 org.springframework.stereotype.Component String className = Type.getType(desc).getClassName(); //将当前类注解加入到annotationSet中 this.annotationSet.add(className); //创建注解属性访问器,将AnnotationMetadataReadingVisitor的attributesMap和metaAnnotationMap放入其中 return new AnnotationAttributesReadingVisitor( className, this.attributesMap, this.metaAnnotationMap, this.classLoader); }
ClassMetadataReadingVisitor.java
public void visit(int version, int access, String name, String signature, String supername, String[] interfaces) { //封装当前类的className,从字节码中解析出来的类名"/"替换成"," this.className = ClassUtils.convertResourcePathToClassName(name); // ACC_INTERFACE 的值是0x0200,而当前类的访问修饰符是0x0021,两者相与为0,因此不是接口,其他变量亦是如此 this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0); this.isAnnotation = ((access & Opcodes.ACC_ANNOTATION) != 0); this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0); this.isFinal = ((access & Opcodes.ACC_FINAL) != 0); if (supername != null && !this.isInterface) { //当前类不是接口,肯定有父类 this.superClassName = ClassUtils.convertResourcePathToClassName(supername); } this.interfaces = new String[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { //如果当前类有接口,则保存所有的接口名到interfaces中 this.interfaces[i] = ClassUtils.convertResourcePathToClassName(interfaces[i]); } }
ClassReader.java
private int readAnnotationValues(int v, final char[] buf, final boolean named, final AnnotationVisitor av) { int i = readUnsignedShort(v); v += 2; if (named) { for (; i > 0; --i) { //读取注解中的所有值 v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); } } else { for (; i > 0; --i) { v = readAnnotationValue(v, buf, null, av); } } if (av != null) { av.visitEnd(); } return v; }
ClassReader.java
private int readAnnotationValue(int v, final char[] buf, final String name, final AnnotationVisitor av) { int i; if (av == null) { switch (b[v] & 0xFF) { case 'e': // enum_const_value return v + 5; case '@': // annotation_value return readAnnotationValues(v + 3, buf, true, null); case '[': // array_value return readAnnotationValues(v + 1, buf, false, null); default: return v + 3; } } switch (b[v++] & 0xFF) { case 'I': // pointer to CONSTANT_Integer case 'J': // pointer to CONSTANT_Long case 'F': // pointer to CONSTANT_Float case 'D': // pointer to CONSTANT_Double av.visit(name, readConst(readUnsignedShort(v), buf)); v += 2; break; case 'B': // pointer to CONSTANT_Byte av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'Z': // pointer to CONSTANT_Boolean av.visit(name, readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE : Boolean.TRUE); v += 2; break; case 'S': // pointer to CONSTANT_Short av.visit(name, (short) readInt(items[readUnsignedShort(v)])); v += 2; break; case 'C': // pointer to CONSTANT_Char av.visit(name, (char) readInt(items[readUnsignedShort(v)])); v += 2; break; case 's': // pointer to CONSTANT_Utf8 //注解中配置的属性,以及属性对应常量池中的值,保存到attributes中,这里主要是将value -> xxxx 保存进去 av.visit(name, readUTF8(v, buf)); v += 2; break; case 'e': // enum_const_value av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); v += 4; break; case 'c': // class_info av.visit(name, Type.getType(readUTF8(v, buf))); v += 2; break; case '@': // annotation_value v = readAnnotationValues(v + 2, buf, true, av.visitAnnotation(name, readUTF8(v, buf))); break; case '[': // array_value int size = readUnsignedShort(v); v += 2; if (size == 0) { return readAnnotationValues(v - 2, buf, false, av.visitArray(name)); } switch (this.b[v++] & 0xFF) { case 'B': byte[] bv = new byte[size]; for (i = 0; i < size; i++) { bv[i] = (byte) readInt(items[readUnsignedShort(v)]); v += 3; } av.visit(name, bv); --v; break; case 'Z': boolean[] zv = new boolean[size]; for (i = 0; i < size; i++) { zv[i] = readInt(items[readUnsignedShort(v)]) != 0; v += 3; } av.visit(name, zv); --v; break; case 'S': short[] sv = new short[size]; for (i = 0; i < size; i++) { sv[i] = (short) readInt(items[readUnsignedShort(v)]); v += 3; } av.visit(name, sv); --v; break; case 'C': char[] cv = new char[size]; for (i = 0; i < size; i++) { cv[i] = (char) readInt(items[readUnsignedShort(v)]); v += 3; } av.visit(name, cv); --v; break; case 'I': int[] iv = new int[size]; for (i = 0; i < size; i++) { iv[i] = readInt(items[readUnsignedShort(v)]); v += 3; } av.visit(name, iv); --v; break; case 'J': long[] lv = new long[size]; for (i = 0; i < size; i++) { lv[i] = readLong(items[readUnsignedShort(v)]); v += 3; } av.visit(name, lv); --v; break; case 'F': float[] fv = new float[size]; for (i = 0; i < size; i++) { fv[i] = Float .intBitsToFloat(readInt(items[readUnsignedShort(v)])); v += 3; } av.visit(name, fv); --v; break; case 'D': double[] dv = new double[size]; for (i = 0; i < size; i++) { dv[i] = Double .longBitsToDouble(readLong(items[readUnsignedShort(v)])); v += 3; } av.visit(name, dv); --v; break; default: v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); } } return v; }
RecursiveAnnotationAttributesVisitor.java
public final void visitEnd() { try { Class<?> annotationClass = this.classLoader.loadClass(this.annotationType); doVisitEnd(annotationClass); } catch (ClassNotFoundException ex) { logger.debug("Failed to class-load type while reading annotation metadata. " + "This is a non-fatal error, but certain annotation metadata may be unavailable.", ex); } }
AnnotationAttributesReadingVisitor.java
public void doVisitEnd(Class<?> annotationClass) { super.doVisitEnd(annotationClass); List<AnnotationAttributes> attributes = this.attributesMap.get(this.annotationType); if (attributes == null) { this.attributesMap.add(this.annotationType, this.attributes); } else { attributes.add(0, this.attributes); } Set<String> metaAnnotationTypeNames = new LinkedHashSet(); Annotation[] metaAnnotations = AnnotationUtils.getAnnotations(annotationClass); if (!ObjectUtils.isEmpty(metaAnnotations)) { for (Annotation metaAnnotation : metaAnnotations) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(metaAnnotation)) { recursivelyCollectMetaAnnotations(metaAnnotationTypeNames, metaAnnotation); } } } if (this.metaAnnotationMap != null) { this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames); } }
RecursiveAnnotationAttributesVisitor.java
protected void doVisitEnd(Class<?> annotationClass) { //获取注解所有的默认值,如果用户配置了,就不再配置 registerDefaultValues(annotationClass); }
private void registerDefaultValues(Class<?> annotationClass) { //注解必需是public的 if (Modifier.isPublic(annotationClass.getModifiers())) { //获取注解所有的方法 Method[] annotationAttributes = annotationClass.getMethods(); //遍历注解内所有的方法 for (Method annotationAttribute : annotationAttributes) { //获取注解属性名 String attributeName = annotationAttribute.getName(); //获取注解属性默认值 Object defaultValue = annotationAttribute.getDefaultValue(); //默认值不为空,并且attributes中不包含此属性名,大概就是说,用户自己没有配置值 if (defaultValue != null && !this.attributes.containsKey(attributeName)) { //如果注解属性的默认值是注解 if (defaultValue instanceof Annotation) { defaultValue = AnnotationAttributes.fromMap(AnnotationUtils.getAnnotationAttributes( (Annotation) defaultValue, false, true)); } //如果注解属性的默认值是注解数组 else if (defaultValue instanceof Annotation[]) { Annotation[] realAnnotations = (Annotation[]) defaultValue; AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length]; for (int i = 0; i < realAnnotations.length; i++) { mappedAnnotations[i] = AnnotationAttributes.fromMap( AnnotationUtils.getAnnotationAttributes(realAnnotations[i], false, true)); } defaultValue = mappedAnnotations; } //将得到的属性保存到map中 this.attributes.put(attributeName, defaultValue); } } } }
AnnotationAttributesReadingVisitor.java
private void recursivelyCollectMetaAnnotations(Set visited, Annotation annotation) { String annotationName = annotation.annotationType().getName(); //注解包名不是以java.lang.annotation开头的 if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation) && visited.add(annotationName)) { //注解的类型是public类型 if (Modifier.isPublic(annotation.annotationType().getModifiers())) { this.attributesMap.add(annotationName, AnnotationUtils.getAnnotationAttributes(annotation, false, true)); //获取当前注解的所有注解 for (Annotation metaMetaAnnotation : annotation.annotationType().getAnnotations()) { //递归调用 recursivelyCollectMetaAnnotations 方法 recursivelyCollectMetaAnnotations(visited, metaMetaAnnotation); } } } }
当程序执行完这里,Spring己经将类注解己经解析并保存完全了。在
annotationSet:保存当前类所配置的注解名
metaAnnotationMap:metaAnnotationMap是Map<String, Set<String>>类型,key保存是当前类注解名,value是一个Set集合,保存着当前类注解的所有父注解名。
attributesMap:是一个LinkedMultiValueMap<String, AnnotationAttributes>当前类注解及父注解中,所有注解方法的默认值及用户自己配置的值。比如在本例中,用户配置了@Service注解的属性value为xxxx,而用户同时还配置了@MyTestAnnotation注解,但是@MyTestAnnotation又配置了@MyRequestAnnotation注解,而@MyRequestAnnotation又配置了@Service注解,因此,在attributesMap中的org.springframework.stereotype.Service中有两个属性AnnotationAttributes
可能对于Java字节码不太了解的小伙伴觉得这写的是什么鬼,程序代码中有太多的+2,+4 ,+8 这些东西,那这些东西是什么呢?其实u+2 ,u+4
比如随便一段字节码 -54, -2, -70, -66, 0, 0, 0, 51, 0, 47, 10, 0, 10, 0, 34, 8, 0, 35 ,前面4个字节码表示魔数,后面4个字节表示版本号,如果要读取常量池中的个数,那么字节码的索引下标u 就要+8 ,此时,才能读取常量池中常量个数为47个 ,因此在本文中看到的代码 u +2 ,u +=2 这些主要是为了跳过一些不需要处理的字节而已。当我们抛开繁索的字节码处理,再来看代码,就觉得Spring通过ASM来获取注解其实非常简单了。Spring从字节码中读取注解,再读取用户配置的注解属性值,再递归读取注解配置的所有注解(不包括java.lang.annotaion包开头的注解)的不为空的默认属性。保存到attributesMap中而已。
经过上面的读取,下面,我们继续跟踪代码,看Spring中如何创建bean的定义的。
ClassPathScanningCandidateComponentProvider.java
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { //看是否配置了@Conditional注解,如果配置了,看是否满足条件跳过,当前程序中肯定是return true 的 return isConditionMatch(metadataReader); } } return false; }
AbstractTypeHierarchyTraversingFilter.java
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //类中所有注解,包含注解的注解,看有没有@Component修饰的 if (matchSelf(metadataReader)) { return true; } ClassMetadata metadata = metadataReader.getClassMetadata(); if (matchClassName(metadata.getClassName())) { return true; } if (this.considerInherited) { if (metadata.hasSuperClass()) { Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName()); if (superClassMatch != null) { if (superClassMatch.booleanValue()) { return true; } } else { try { if (match(metadata.getSuperClassName(), metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read super class [" + metadata.getSuperClassName() + "] of type-filtered class [" + metadata.getClassName() + "]"); } } } } if (this.considerInterfaces) { for (String ifc : metadata.getInterfaceNames()) { // Optimization to avoid creating ClassReader for super class Boolean interfaceMatch = matchInterface(ifc); if (interfaceMatch != null) { if (interfaceMatch.booleanValue()) { return true; } } else { // Need to read interface to determine a match... try { if (match(ifc, metadataReaderFactory)) { return true; } } catch (IOException ex) { logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" + metadata.getClassName() + "]"); } } } } return false; }
我们继续回到bean的定义代码
AnnotationScopeMetadataResolver.java
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { ScopeMetadata metadata = new ScopeMetadata(); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType); if (attributes != null) { metadata.setScopeName(attributes.getAliasedString("value", this.scopeAnnotationType, definition.getSource())); ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = this.defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); } } return metadata; }
AnnotationConfigUtils.java
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) { return attributesFor(metadata, annotationClass.getName()); }
AnnotationConfigUtils.java
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) { return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false)); }
MethodMetadataReadingVisitor.java
public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) { AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes( this.attributesMap, this.metaAnnotationMap, annotationName); return AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString); }
public static AnnotationAttributes getMergedAnnotationAttributes( LinkedMultiValueMap<String, AnnotationAttributes> attributesMap, Map<String, Set<String>> metaAnnotationMap, String annotationName) { //这里显然,没有配置Scope注解,因此返回值为null List<AnnotationAttributes> attributesList = attributesMap.get(annotationName); if (attributesList == null || attributesList.isEmpty()) { return null; } //纵观下面的注解属性合并代码,假如 A 注解中有 value,a,b,c属性,先提取出value属性,再遍历这个类中 //所有的注解及注解的注解,看其他注解中有没有不为空的a,b,c属性,如果有,则保存到results中 //获取当前属性的第一个元素 AnnotationAttributes results = new AnnotationAttributes(attributesList.get(0)); Set<String> overridableAttributeNames = new HashSet<String>(results.keySet()); //排除当前注解的value属性 overridableAttributeNames.remove(AnnotationUtils.VALUE); List<String> annotationTypes = new ArrayList<String>(attributesMap.keySet()); Collections.reverse(annotationTypes); //将当前注解从所有的注解中移除 annotationTypes.remove(annotationName); for (String currentAnnotationType : annotationTypes) { List<AnnotationAttributes> currentAttributesList = attributesMap.get(currentAnnotationType); if (!ObjectUtils.isEmpty(currentAttributesList)) { Set<String> metaAnns = metaAnnotationMap.get(currentAnnotationType); if (metaAnns != null && metaAnns.contains(annotationName)) { AnnotationAttributes currentAttributes = currentAttributesList.get(0); for (String overridableAttributeName : overridableAttributeNames) { Object value = currentAttributes.get(overridableAttributeName); if (value != null) { //如果不为空,则保存属性 results.put(overridableAttributeName, value); } } } } } return results; }
经过层层解析,发现用户没有配置scope属性,因此,这里对象是单例。
AnnotationBeanNameGenerator.java
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { if (definition instanceof AnnotatedBeanDefinition) { String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition); if (StringUtils.hasText(beanName)) { // Explicit bean name found. return beanName; } } // Fallback: generate a unique default bean name. return buildDefaultBeanName(definition, registry); }
AnnotationBeanNameGenerator.java
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) { AnnotationMetadata amd = annotatedDef.getMetadata(); Set<String> types = amd.getAnnotationTypes(); String beanName = null; //遍历当前的所有注解 for (String type : types) { AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type); if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) { Object value = attributes.get("value"); if (value instanceof String) { String strVal = (String) value; //如果用户配置多个注解,并且注解的value值不为空,且不相等,将抛出异常 if (StringUtils.hasLength(strVal)) { if (beanName != null && !strVal.equals(beanName)) { throw new IllegalStateException("Stereotype annotations suggest inconsistent " + "component names: '" + beanName + "' versus '" + strVal + "'"); } beanName = strVal; } } } } //得到beanName return beanName; }
AnnotationConfigUtils.java
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); } static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { //是否配置了Lazy注解,如果配置了,取value值设置为lazyInit值 if (metadata.isAnnotated(Lazy.class.getName())) { abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value")); } else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) { abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value")); } //是否配置了@Primary注解 if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } //是否配置了@DependsOn注解 if (metadata.isAnnotated(DependsOn.class.getName())) { abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value")); } if (abd instanceof AbstractBeanDefinition) { AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd; //是否配置了@Role注解 if (metadata.isAnnotated(Role.class.getName())) { absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue()); } //是否配置了@Description注解 if (metadata.isAnnotated(Description.class.getName())) { absBd.setDescription(attributesFor(metadata, Description.class).getString("value")); } } }
到这里,我们终于将注解创建Bean的定义解析完成了。下面我们来总结一下。
- 通过字节码解析得到类的所有注解
- 根据注解信息封装BeanDefinition中所有的所有的属性
- 注册BeanDefinition
关于注解的属性注入,在下一篇博客中再来分析了
本文的 github 地址是
https://github.com/quyixiao/spring_tiny/tree/master/src/main/java/com/spring_1_100/test_31_40/test35_resource_inject