Spring源码深度解析(郝佳)-学习-源码解析-基于注解bean定义(一)

我们在之前的博客 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的定义解析完成了。下面我们来总结一下。

  1. 通过字节码解析得到类的所有注解
  2. 根据注解信息封装BeanDefinition中所有的所有的属性
  3. 注册BeanDefinition

关于注解的属性注入,在下一篇博客中再来分析了

本文的 github 地址是
https://github.com/quyixiao/spring_tiny/tree/master/src/main/java/com/spring_1_100/test_31_40/test35_resource_inject

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值