生成BeanDefinition
- 本文源码基于spring-framework-5.3.10
- Spring启动的时候会进行扫描。
- 扫描入口:org.springframework.context.annotation.ClassPathBeanDefinitionScanner中public int scan(String... basePackages)方法
- 扫描的核心方法:org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider中scanCandidateComponents(String basePackage)方法
- 这一步主要作用是用来生成BeanDefinition,方便后续使用。
源码重点关注内容
- BeanDefinition是如何生成的?
- 什么样的对象会生成BeanDefinition。
生成BeanDefinition的主要流程
- 首先,通过ResourcePatternResolver获得指定包路径下的所有.class文件(Spring源码中将此文件包装成了Resource对象)
- 遍历每个Resource对象。
- 利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader)。
- 利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选(条件注解并不能理解:某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。)。
- 筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition。
- 再基于metadataReader判断是不是对应的类是不是接口或抽象类。
- 如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集。
扫描的入口scan方法源码分析
/**
* 扫描的入口
*/
public int scan(String... basePackages) {
// 得到当前已经注册了多少个BeanDefinition
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
// 尝试去扫描的逻辑,扫描的核心代码
doScan(basePackages);
// Register annotation config processors, if necessary.
// 如有必要,注册注解配置处理器。
// 这里不是本文的重点,主要对bean的信息进行完善
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
// 返回:本次扫描时注册的bean的个数 = 当前bean的个数 - 没扫描前bean的个数 =
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
扫描的核心doScan源码分析
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 传入的包路径是空的!抛异常
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 定义BeanDefinitionHolder(他是BeanDefinition封装了一层)的一个集合
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 遍历所有的包路径
for (String basePackage : basePackages) {
// 找到所有的BeanDefinition候选者
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 遍历所有的BeanDefinition候选者
for (BeanDefinition candidate : candidates) {
// 获取Bean定义类中@Scope注解的详细信息,即获取Bean的作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
// 设置这个BeanDefinition的Scope属性
candidate.setScope(scopeMetadata.getScopeName());
// 获取Bean的名字:有名字获取配置的名字,没有名字根据当前类进行获取:类名前俩位都大写,直接返回类名;前俩位不是大写,返回首字母小写的名称;
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 给BeanDefinition赋一些默认值
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 解析@Lazy、@Primary、@DependsOn、@Role、@Description注解
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 检查Spring容器中是否已经存在该beanName
if (checkCandidate(beanName, candidate)) {
// 把BeanDefinition封装为BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 根据Scope的类型,来确认是否需要生产代理对象
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册到beanDefinitionMap
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
// 返回所有的beanDefinition
return beanDefinitions;
}
找到所有的BeanDefinition候选者:findCandidateComponents源码分析
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
// 如果存在索引,并且索引的类都可以成为bean。使用带有索引的方式生成BeanDefinition。(用的较少,源码else里面的很类似,可能性能相对高一点,这里不详细分析)
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
// 扫描包含Component注解的可成为Bean的方法:大部分情况下走的扫描方法
return scanCandidateComponents(basePackage);
}
}
/**
* 扫描包含Component注解的可成为Bean的方法
*/
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
// 定义返回值的变量
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// 获取basePackage下所有的文件资源:classpath*:com/cangqiong/**/*.class
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 得到当前路径下的所有的文件资源。所有的编译后的class文件
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
// 俩个日志的标记
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
// 遍历每一个class文件
for (Resource resource : resources) {
// 日志打印
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
// 当这个资源可读并且存在的时候
if (resource.isReadable()) {
try {
// 得到当前资源的元数据,这里通过ASM(字节码直接解析)解析
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// excludeFilters、includeFilters判断,scan中配置的参数。
if (isCandidateComponent(metadataReader)) { // @Component-->includeFilters判断
// 构建扫描生成的BeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
// 将当前的资源设置到读取好的元数据中
sbd.setSource(resource);
// 判断这个class:(他是顶级的类(不是内部类)或者他是静态内部类)并且 (不是接口不是抽象的 或者 他是抽象的并且有任意一个方法上有Lookup注解) 返回为true
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
// 条件到BeanDefinition候选者中
candidates.add(sbd);
}
else {
// 无法添加当前类为bean的时候,打印日志
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
else {
// 当前类不能成为bean,打印日志
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;
}
/**
* excludeFilters、includeFilters判断,scan中配置的参数。
*/
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
// 满足excludeFilters的条件,直接返回false
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
// 符合includeFilters的会进行条件匹配,通过了才是Bean,也就是先看有没有@Component,再看是否符合@Conditional。都满足后,今天条件匹配(继承condition类的方法)
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
// 没有匹配上,返回false
return false;
}
/**
* 构建扫描生成的BeanDefinition
*/
public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
// 非空判断,抛异常!
Assert.notNull(metadataReader, "MetadataReader must not be null");
// 得到元数据
this.metadata = metadataReader.getAnnotationMetadata();
// 这里只是把className设置到BeanDefinition中!!!!
setBeanClassName(this.metadata.getClassName());
// 设置resource
setResource(metadataReader.getResource());
}
/**
* 校验Bean是否之前存在
*/
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
// Bean之前不存在,直接返回true
if (!this.registry.containsBeanDefinition(beanName)) {
return true;
}
BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
if (originatingDef != null) {
existingDef = originatingDef;
}
// 是否兼容,如果兼容返回false(同一个类被重复扫描的时候)表示不会重新注册到Spring容器中,如果不兼容则会抛异常。
if (isCompatible(beanDefinition, existingDef)) {
return false;
}
// 不兼容的时候抛异常
throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +
"' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +
"non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
}
结束语
- 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
- 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解!
- 关注公众号,后续持续高效的学习JVM!
- 这个公众号,无广告!!!每日更新!!!