2.1、spring之注解转换为BeanDefinition
spring支持注解@Component,@Controller,有此类注解的类会自动注册为一个bean,所有bean在生成之前都由一个BeanDefinition解析而来。假设如果我们自己来写处理注解的过程
(1)读取项目中的所有类,判断类是否包含指定的注解。
(2)如果包含对应的注解,根据注解生成对应的BeanDefinition。
(3)将生成的BeanDefinition存储起来
spring 也是按照我们上面的操作来进行。
spring中存在ClassPathBeanDefinitionScanner
类和ClassPathScanningCandidateComponentProvider
,用来搜索包含指定注解的类,并生成对应的BeanDefinition(ScannedGenericBeanDefinition
)或者生成BeanDefinitionHolder
一、扫描并解析
spring 将 这一操作放在ClassPathScanningCandidateComponentProvider
的findCandidateComponents
方法中
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
try {
// 1、获取对应路径下的所有类
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable()) {
try {
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
// 2、判断是否包含指定的注解或者其他的条件
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
.....
return candidates;
}
2.1 获取所有的文件
可以参考 https://blog.csdn.net/liu20111590/article/details/89180320
2.2 判断条件
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)) {
return isConditionMatch(metadataReader);
}
}
return false;
}
从上面可以看到,对于条件的判断是采用的TypeFilter来进行的。接下来我们可以来详细了解一下TypeFilter
二、存储BeanDefinition
spring 自行实现了一部分,当然我们可以不使用spring实现,自行实现也可以。
在ClassPathBeanDefinitionScanner
的doScan
方法中
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
for (String basePackage : basePackages) {
// 1、获取符合条件的类并生成对应的BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 2、生成bean的名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 3、判断是否生成过了,如果没有重新存储
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
三、TypeFilter详解
3.1 TypeFilter接口和继承关系图
3.1.1 接口信息
TypeFilter接口
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException;
我们看到其中只有一个方法,既match方法,符合规则返回true,不符合返回false。
我们可以看一下入参:、MetadataReader
接口:
//所在的Resource
Resource getResource();
// 类的元素信息
ClassMetadata getClassMetadata();
// 类中的所有注解,包含方法上的注解
AnnotationMetadata getAnnotationMetadata();
从这里,我们可以获取到当前类的所有信息
3.1.2 类继承关系
3.2 常用的TypeFilter
3.2.1 具有继承关系的处理
AbstractTypeHierarchyTraversingFilter
:
用来处理那些存在继承关系的接口和类,根据配置,会扫描所有的父类和所有实现的接口。此类是抽象类,如果有具体的实现类不满足要求,可以自行继承实现。
我们可以看两个具体的实现类。AnnotationTypeFilter
用来处理包含指定注解的类AssignableTypeFilter
用来处理是否是指定类型
3.2.2 Aspectj支持
AspectJTypeFilter
用来处理对AspectJ类型的支持
3.2.3 单独对类的处理
AbstractClassTestingTypeFilter
是一个单独对类信息的抽象类。我们可以看一下如下的代码。指定了抽象方法,只处理类信息相关。
@Override
public final boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
return match(metadataReader.getClassMetadata());
}
protected abstract boolean match(ClassMetadata metadata);
RegexPatternTypeFilter
是上方的一个实现类。主要是判断类的名字
是否满足给定的调校