Spring扫描底层流程详解
2022-11-23 17:37:47 0 举报
为你推荐
查看更多
Spring扫描底层流程详解
作者其他创作
大纲/内容
循环每个包路径,进行扫描for (String basePackage : basePackages)
throw new ConflictingBeanDefinitionException
注册到beanDefinitionMaps
isCandidateComponent(metadataReader)
循环Set
for (BeanDefinition candidate : candidates)
MetadataReader表示类的元数据读取器,主要包含了一个AnnotationMetadata,功能有1.获取类的名字2.获取父类的名字3.获取所实现的所有接口名4.获取所有内部类的名字5.判断是不是抽象类6.判断是不是接口7.判断是不是一个注解8.获取拥有某个注解的方法集合9.获取类上添加的所有注解信息10.获取类上添加的所有注解类型集合
scanCandidateComponents(String basePackage)
是否兼容,如果兼容返回false表示不会重新注册到Spring容器中
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
生成beanDefinition对象,注意这里只是把className设置到BeanDefinition中
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
扫描得到beanDefinition方法:findCandidateComponents(basePackage)
简单版本:https://www.processon.com/view/link/61370ee60e3e7412ecd95d43
检查Spring容器中是否已经存在该beanName
META-INF/spring.components
获取bean的scope属性 就是singleton 还是prototype 等
,如果不兼容则会抛异常。
!this.registry.containsBeanDefinition(beanName)
设置BeanDefinition的默认值
Set<BeanDefinition> candidates
1.是否懒加载(false)2.setAutowireMode(0)3.setDependencyCheck(0)4.setInitMethodName()5.setEnforceInitMethod(false)6.setDestroyMethodName()7.setEnforceDestroyMethod(false)
存在一样的beanName,但是originatingBeanDefinition不一样,因为放到spring中的是RootbeanDefinition
beanDefinition.applyDefaults(this.beanDefinitionDefaults);
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
beanDefinition设置默认值,还有标记此bean是否能被依赖注入
1.获取指定路径下的所有class文件:classpath*:{basePackage}/**/*.classString packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;2.通过spring封装的资源处理器获取class文件资源,就相当于读取class文件Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);3.循环处理每个class文件for (Resource resource : resources)
类:org.springframework.context.annotation.ClassPathBeanDefinitionScanner.java方法:doScan(String... basePackages)
顶级类还是嵌套类(静态内部类:可以独立于外部类构造) &&抽象类或者是接口 &&(如果是抽象类 && 有Lookup注解的方法)
spring5.3.10
add到candidates集合中返回
1.如果符合excludeFilters的就直接返回false,相当于不扫描此bean2.符合includeFilters的会进行条件匹配,通过了才是Bean,也就是先看有没有@Component,再看是否符合@Conditional
通过类的元数据读取器工厂,读取类的元数据
解析@Lazy、@Primary、@DependsOn、@Role、@Description
AutowireCandidate表示某个Bean能否被用来做依赖注入
beanDefinitionMaps是否包含此beanDefinition
isCandidateComponent(sbd)
扫描MATA_INF文件夹下的spring.components文件,这是spring加快扫描速度的方式,需要在这文件中配置例如:com.rhpass.service.OrderService=org.springframework.stereotype.Component注意:走了文件扫描就不会走注解扫描(@ComponentScan),且文件不为空就会走文件扫描
excludeFilters、includeFilters判断 其中 @Component--includeFilters判断
@Nullableprivate volatile Object beanClass;可以看出beanClass为Object对象,先设置为className,生成bean后才会是Class对象
如果两个@ComponentScan配置的路径重复,则两个beanDefinition一致,这时不需要加入spring容器中,直接返回就行,说明已经存在了此beanDefinition
0 条评论
回复 删除
下一页