我们在之前的博客 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