Spring IOC @ComponentScan源码流程

一、this.reader = new AnnotatedBeanDefinitionReader(this);
注册内置BeanPostProcessor;注册相关BeanDefinition;
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//用来解析配置类的
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
//在这里注册,用于解析配置类
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
注册ConfigurationClassPostProcessor定义,添加到BeanDefinitionMap中,ConfigurationClassPostProcessor用于解析@componentScan注解使用;
二、this.scanner = new ClassPathBeanDefinitionScanner(this);
定义scanner 用于后面或者程序员调用scan()方法扫描包和后面spring自己扫描包使用;
三、refresh();
invokeBeanFactoryPostProcessors(beanFactory);
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
beanFactory.isTypeMatch(ppName, PriorityOrdered.class)
取出所有实现了BeanDefinitionRegistryPostProcessor的类,并且判断是否实现了PriorityOrdered类似的操作还有三次
1、同实现PriorityOrdered,BeanDefinitionRegistryPostProcessor的bean优先级最高会被首先初始化;
2、同实现Ordered,BeanDefinitionRegistryPostProcessor的bean第二优先级执行;
3、只实现了BeanDefinitionRegistryPostProcessor第三优先级执行
4、实现了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessors优先级最低;
第四种优先级的执行了什么:
invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory)
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
enhanceConfigurationClasses(beanFactory);创建cglb动态代理
cglb动态代理:源数据如果带了Configuration注解,那么就会对该数据cglb代理,做了该代理后,那么该类调用其他类的
后,那 么spring会把这个类加到bean定义当中,不需要重复解析。
第一种优先级解析配置类
在我们this.reader = new AnnotatedBeanDefinitionReader(this);方法种的ConfigurationClassPostProcessor种实现了
PriorityOrdered和BeanDefinitionRegistryPostProcessor所有会在这个优先级被执行;
ConfigurationClassPostProcessor实现了postProcessBeanDefinitionRegistry方法
postProcessBeanDefinitionRegistry
processConfigBeanDefinitions(registry);
String[] candidateNames = registry.getBeanDefinitionNames();
获取所有bean定义对象的名称
for (String beanName : candidateNames) {
遍历所有对象
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef))
如果当前bean定义中有@Configuration注解那么加一个full属性
如果是加了@bean@ComponetScan@Import@Componet那么就是不完整的配置类
判断是否是个完整的bean,如果带了Configuration那么就是一个完成的bean,其他的则
是不完整的;
接着创建ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
来解析我们的配置类;
调用他的方法:调用解析方法parser.parse(candidates);
循环配置类for (BeanDefinitionHolder holder : configCandidates)
在继续调用if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
processConfigurationClass(new ConfigurationClass(metadata, beanName));
sourceClass = doProcessConfigurationClass(configClass, sourceClass);开始真正解析我们的配置类
判断是否加了componentScan 注解
Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN))
循环遍历我们所有的ComponentScan
for (BeanDefinitionHolder holder : scannedBeanDefinitions)
解析我们有效的bean定义 然后注册
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
在解析配置类的时候会重新配置一个自己的scan,在最开始的Scan只是定义,在这边被调用;
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean(“useDefaultFilters”), this.environment, this.resourceLoader);获取包扫描路径Set basePackages = new LinkedHashSet<>();
String[] basePackagesArray = componentScan.getStringArray(“basePackages”);
最终扫描
scanner.doScan(StringUtils.toStringArray(basePackages));
扫描所有的包for (String basePackage : basePackages)
找到所有候选的bean定义
Set candidates = findCandidateComponents(basePackage);
return scanCandidateComponents(basePackage);
获取路径通过资源处理器去读取
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + ‘/’ + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
读到所有的类后
判断是否可读
if (resource.isReadable())
判断类型
if (isCandidateComponent(metadataReader))
if (tf.match(metadataReader, getMetadataReaderFactory()))根据策列者设计模式根据不同的类型调用同一个方法
那么我们扫描出来的就是ScannedGenericBeanDefinition 类型的,并且设置他的原路径
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
判断当前类是不是顶级的类,是不是抽象类如果是抽象类必须添加Lookup注解,如果接口就不符合排除掉if (isCandidateComponent(sbd))
如果要和mybati集成的时候就要重写这个类
符合要求加到候选名单中candidates.add(sbd);
Set candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates)
此时我们就拿到我我们自己写的类,使用注解注释的
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
设置默认的bean定义信息,比如是否懒加载,是否自动装配,能否调用InitMethod,销毁等方法
registerBeanDefinition(definitionHolder, this.registry);
注册到this.beanDefinitionMap.put(beanName, beanDefinition);里面

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值