组件
annotation读取主要涉及以下组件
-
AnnotatedBeanDefinitionReader- 读取并注册指定class(es) -
ClassPathBeanDefinitionScanner- 扫描注册指定package 下的bean -
AnnotationConfigUtils- 注册相关BeanFactoryPostProcessor,提供一些common的annotation处理
以及 @Configuration 处理相关的组件
-
ConfigurationClassBeanDefinitionReader- 解析处理 Configuration Bean -
ConfigurationClassPostProcessor- 处理 @Configuration -
ComponentScanAnnotationParser- 处理 @ComponentScan -
ContextNamespaceHandler&ComponentScanBeanDefinitionParser- 处理xml配置中的 component-scan
以及一些辅助类
-
BeanNameGenerator(AnnotationBeanNameGenerator) -
ScopeMetadataResolver(AnnotationScopeMetadataResolver) -
ConditionEvaluator处理 @Conditional
Annotation & BeanDefinition
为了在BeanDefinition中承载annotation, AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 分别使用了 实现了AnnotatedBeanDefinition 的AnnotatedGenericBeanDefinition 和 ScannedGenericBeanDefinition 。
AnnotatedBeanDefinition
AnnotatedBeanDefinition 通过AnnotationMetadata 来暴露annotation及class信息。
public interface AnnotatedBeanDefinition extends BeanDefinition {
AnnotationMetadata getMetadata();
MethodMetadata getFactoryMethodMetadata();
}
AnnotationMetadata
AnnotationMetadata 继承了 ClassMetadata和 AnnotatedTypeMetadata。暴露的接口均以String 的形式表现 annotation 和 class 信息,以便独立于(先于) ClassLoader 读取存储这些metadata。
AnnotatedGenericBeanDefinition使用了 StandardAnnotationMetadata 通过java reflection 获取 annotation/class 信息。
ScannedGenericBeanDefinition 则使用了 AnnotationMetadataReadingVisitor 通过 ASM 读取 annotation/class 信息。
AnnotatedBeanDefinition读取注册
AnnotatedBeanDefinition读取有两种方式
一是使用 AnnotatedBeanDefinitionReader ,传入bean的Class进行读取注册
一是使用 ClassPathBeanDefinitionScanner 扫描classpath 找出符合条件的class进行注册
这一个步骤等价于XmlBeanDefinitionReader 从XMl中读取注册bean。而具体处理@Configuration @Import 等等的操作会留给 ConfigurationClassPostProcessor 处理。这样也使得xml 读取的bean,如果需要,同样可以使用 @Configuration 等annotation。
AnnotatedBeanDefinitionReader
初始化
AnnotatedBeanDefinitionReader 创建时会用 AnnotationConfigUtils.registerAnnotationConfigProcessors(BeanDefinitionRegistry) 向registry 注册annotation 相关的BeanFactoryPostProcessor
registerBean
AnnotatedBeanDefinitionReader 的读取很简单。由于 Java Config 不涉及像XML Config 中的 constructor-arg, property-value 等等的配置,所以只需要关注一些Bean基本的属性即可。
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 1. 创建 AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
// 2. 检查 @Conditional
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
...
// 3. 检查设置Scope
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 4. 获取Bean Name
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 5. 处理 @Lazy, @Primary, @DependesOn, @Role, D@escription
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
...
// 6. 向registry 注册
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
ClassPathBeanDefinitionScanner
初始化
- 设置filters,主要是添加了
new AnnotationTypeFilter(Component.class)来过滤有 @Comonent 的class - 设置
ResourcePatternResolver, 用来读取class 文件 - 设置
MetadataReaderFactory为CachingMetadataReaderFactory,对应生成SimpleMetadataReader类型的MetadataReader - 读取之前执行时生成的 componentsIndex
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
this.registry = registry;
if (useDefaultFilters) {
registerDefaultFilters();
}
setEnvironment(environment);
setResourceLoader(resourceLoader);
}
public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
this.componentsIndex = CandidateComponentsIndexLoader.loadIndex(this.resourcePatternResolver.getClassLoader());
}
scan
doScan(String... basePackages)
- 调用
findCandidateComponents扫描获得所有能通过filter 的class的BeanDefinition - 类似
AnnotatedBeanDefinitionReader一样处理和注册bean
findCandidateComponents(String basePackage)
findCandidateComponents 从 componentsIndex 读取或者直接扫描classpath
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}
scanCandidateComponents(String basePackage)
- 使用
ResourcePatternResolver加载所有在classpath*:{basepakcage}/**/*.class上的class。 - 遍历class Resource,对每个resource, 生成
SimpleMetadataReader读取resource -
ScannedGenericBeanDefinition存储通过 metaReader 获取的 AnnotationMetaData 生成 BeanDefinition
classpath*: 和 classpath: 的区别在于:
classpath*:会搜索所有classpath 上满足条件的class, classpath: 只会找到满足条件的第一个。``classpath:`如果没有找到的话会break
// ClassPathScanningCandidateComponentProvider
// with try..catch, else {}, logging removed
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
}
}
}
return candidates;
}
// ScannedGenericBeanDefinition
public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
Assert.notNull(metadataReader, "MetadataReader must not be null");
this.metadata = metadataReader.getAnnotationMetadata();
setBeanClassName(this.metadata.getClassName());
}
SimpleMetadataReader
使用了repackage 的 ASM
- 使用
ClassReader读入class 文件 - 利用
AnnotationMetadataReadingVisitor从ClassReader读取 annotation/class 信息
//SimpleMetadataReader
SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
InputStream is = new BufferedInputStream(resource.getInputStream());
ClassReader classReader;
try {
classReader = new ClassReader(is);
}
catch (IllegalArgumentException ex) {
throw new NestedIOException("ASM ClassReader failed to parse class file - " +
"probably due to a new Java class file version that isn't supported yet: " + resource, ex);
}
finally {
is.close();
}
AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
this.annotationMetadata = visitor;
// (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
this.classMetadata = visitor;
this.resource = resource;
}










网友评论