【接上文】
- @ImportResource
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
这里的处理相对简单,就是把注解里的location解析出来,做变量替换然后保存到configClass的ImportResource map中去。
调用的位置是在parse解析完了以后通过loadBeanDefinition…的方法调用的,这个后面再说。
- @Bean
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
/**
* Retrieve the metadata for all <code>@Bean</code> methods.
* 获取所有@Bean注解的方法元信息
*/
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
AnnotationMetadata original = sourceClass.getMetadata();
Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
//判断方法集合是否超过两个,并且类的元数据是StandardAnnotationMetadata实例,则从ASM内获取声明的方法顺序
if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
try {
// 尝试通过ASM从类文件判断方法的顺序...因为,JVM的标准反射库获取的方法顺序是随机的,
// 甚至泡在相同JVM的不同应用返回的顺序也会不一致
AnnotationMetadata asm =
this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
if (asmMethods.size() >= beanMethods.size()) {
Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
for (MethodMetadata asmMethod : asmMethods) {
for (MethodMetadata beanMethod : beanMethods) {
if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
selectedMethods.add(beanMethod);
break;
}
}
}
if (selectedMethods.size() == beanMethods.size()) {
// All reflection-detected methods found in ASM method set -> proceed
beanMethods = selectedMethods;
}
}
}
catch (IOException ex) {
logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
// No worries, let's continue with the reflection metadata we started with...
}
}
return beanMethods;
}
解析@Bean注解的方法,存到configClass的beanMethod对应的map。
- interface
/**
* Register default methods on interfaces implemented by the configuration class.
* 获取接口上的bean注解方法
*/
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
for (SourceClass ifc : sourceClass.getInterfaces()) {
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
for (MethodMetadata methodMetadata : beanMethods) {
if (!methodMetadata.isAbstract()) {
// A default method or other concrete method on a Java 8+ interface...
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
}
processInterfaces(configClass, ifc);
}
}
private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
public void addBeanMethod(BeanMethod method) {
this.beanMethods.add(method);
}
获取接口及及包含默认实现的接口方法, 然后封装成BeanMethod 添加到configClass的beanMethods中。
后续就是解析父类,添加到knownSuperClasses
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
到这里ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法就解析完成了。
【NEXT】
对invokeBeanFactoryPostProcessor这个方法的整体脉络做整体审视和总结。