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
是上方的一個實現類。主要是判斷類的名字
是否滿足給定的調校