温州中豪网站建设推广宁波企业网站优化报价
web/
2025/9/25 17:22:08/
文章来源:
温州中豪网站建设推广,宁波企业网站优化报价,仓储设备东莞网站建设,前端网页设计师简介
前面介绍了scanner可以扫描某个包路径下的所有bean#xff0c;我们最常用的也是通过ComponentScan指定包路径去扫描#xff0c;在SpringBoot中也是如此#xff0c;本文将介绍spring扫描的逻辑
BeanDefinitionRegistryPostProcessor
知道了ComponentScan的作用#…简介
前面介绍了scanner可以扫描某个包路径下的所有bean我们最常用的也是通过ComponentScan指定包路径去扫描在SpringBoot中也是如此本文将介绍spring扫描的逻辑
BeanDefinitionRegistryPostProcessor
知道了ComponentScan的作用那么spring什么时候开始解析ComponentScan去扫描bean呢
这个时候就要知道spring的其中一个生命周期 BeanDefinitionRegistryPostProcessor
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}该生命周期可以说是最早的一个还在BeanFactoryPostProcessor#postProcessBeanFactory之前执行
从接口提供的方法就很明确可以自己去注册一些bean
那么在该接口实现类里面就可以将最开始注册的AppConfig类拿出来确定有ComponentScan注解就可以拿到路径去扫描最终注册bean
ConfigurationClassPostProcessor
ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor
在spring中通过该类进行配置类的解析并且注册bean只不过在spring中标名是一个配置类的注解多种多样 ComponentScan 也只是其中一个
本文主要讲 ComponentScan 其它配置类后面讲 注册 源码链路 AnnotationConfigApplicationContext(Class?… componentClasses) # 进入this() AnnotationConfigApplicationContext() AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Nullable Object source)
可以看到这么一行 注册ConfigurationClassPostProcessor
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 进入refresh方案spring最重要的一个方法整个生命周期都在这
AnnotationConfigApplicationContext(Class?… componentClasses) # 进入this()AbstractApplicationContext#refresh()AbstractApplicationContext.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory); 处理 BeanFactory的后置处理器PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors)
会看到如下代码
// 获取BeanDefinitionRegistryPostProcessor一般来说就只有一个 ConfigurationClassPostProcessor
String[] postProcessorNames beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}
}
// 排个序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行 BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();// 扫描完之后还有可能生成BeanFactoryPostProcessor
postProcessorNames beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {// 过滤之前执行过的BeanFactoryPostProcessorif (!processedBeans.contains(ppName) beanFactory.isTypeMatch(ppName, Ordered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();以上就是获取 ConfigurationClassPostProcessor 到执行它的 postProcessBeanDefinitionRegistry方法的 逻辑通过beanFactory.getBeanNamesForType 获取 BeanDefinitionRegistryPostProcessor
将获取到的BeanDefinitionRegistryPostProcessor 排个序通过Order注解或者javax.annotation.Priority注解确定排序
遍历执行postProcessBeanDefinitionRegistry方法
解析 ComponentScan
那么在ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry又是怎么解析ComponentScan注册bean呢
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistryConfigurationClassPostProcessor#processConfigBeanDefinitions(BeanDefinitionRegistry registry) 在这里会有一个检查判断是不是配置类 ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) 那么什么是配置类呢
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {// getFactoryMethodName表示是Bean方式注入的bean这种不作为配置类String className beanDef.getBeanClassName();// 注解信息通过MetadataReader获取ASM技术 并没有加载类AnnotationMetadata metadata;// 如果AnnotatedBeanDefinition则直接取AnnotationMetadataif (beanDef instanceof AnnotatedBeanDefinition className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {metadata ((AnnotatedBeanDefinition) beanDef).getMetadata();}// 如果是AbstractBeanDefinition则解析beanClass得到AnnotationMetadataelse if (beanDef instanceof AbstractBeanDefinition ((AbstractBeanDefinition) beanDef).hasBeanClass()) {metadata AnnotationMetadata.introspect(beanClass);}else {// ASM技术这里其实也是spring提供的一个工具我们也可以使用后续文章介绍MetadataReader metadataReader metadataReaderFactory.getMetadataReader(className);metadata metadataReader.getAnnotationMetadata();}MapString, Object config metadata.getAnnotationAttributes(Configuration.class.getName());// 存在Configuration并且proxyBeanMethods不为false就是配置类 配置类型为Fullif (config ! null !Boolean.FALSE.equals(config.get(proxyBeanMethods))) {// 设置属性configurationClass表示是配置类beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);}// 存在Configuration并且proxyBeanMethods为false时也是配置类配置类型为lite// 不存在Configuration存在Component、ComponentScan、Import、ImportResource中的某一个也是配置类 配置类型为lite// 有Bean标注的方法也是配置类else if (config ! null || isConfigurationCandidate(metadata)) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);}else {return false;}// Its a full or lite configuration candidate... Lets determine the order value, if any.Integer order getOrder(metadata);if (order ! null) {// 配置类也可以排序使用 Order注解beanDef.setAttribute(ORDER_ATTRIBUTE, order);}return true;}private static final SetString candidateIndicators new HashSet(8);static {candidateIndicators.add(Component.class.getName());candidateIndicators.add(ComponentScan.class.getName());candidateIndicators.add(Import.class.getName());candidateIndicators.add(ImportResource.class.getName());}public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {// 接口不管if (metadata.isInterface()) {return false;}// 只要存在Component、ComponentScan、Import、ImportResource四个中的一个就是lite配置类for (String indicator : candidateIndicators) {if (metadata.isAnnotated(indicator)) {return true;}}// Finally, lets look for Bean methods...// 只要存在Bean注解了的方法就是lite配置类return hasBeanMethods(metadata);
}根据上面的代码逻辑分析拥有Configuration Component、ComponentScan、Import、ImportResource 或者方法有Bean注解那么就是一个配置类继续后面代码分析
parser.parse(candidates); candidates 就是找出的所有配置累会进入 ConfigurationClassParser#parse(AnnotationMetadata metadata, String beanName)ConfigurationClassParser#processConfigurationClass(ConfigurationClass configClass, Predicate filter)ConfigurationClassParser#doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
其它配置类先不看那么会看到会看到如下代码
// 查看是否有ComponentScan注解
SetAnnotationAttributes componentScans AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {// The config class is annotated with ComponentScan - perform the scan immediatelySetBeanDefinitionHolder scannedBeanDefinitions this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// Check the set of scanned definitions for any further config classes and parse recursively if neededfor (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand holder.getBeanDefinition().getOriginatingBeanDefinition();if (bdCand null) {bdCand holder.getBeanDefinition();}// 解析出来还有配置类继续解析if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {parse(bdCand.getBeanClassName(), holder.getBeanName());}}}
}查看该Bean的有没有ComponentScans或者ComponentScan注解如果有那么使用ComponentScanAnnotationParser解析
public SetBeanDefinitionHolder parse(AnnotationAttributes componentScan, final String declaringClass) {ClassPathBeanDefinitionScanner scanner new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean(useDefaultFilters), this.environment, this.resourceLoader);// bean的名字生成器默认是首字母小写的类名可以自己定义其它规则比如类的全限定名Class? extends BeanNameGenerator generatorClass componentScan.getClass(nameGenerator);boolean useInheritedGenerator (BeanNameGenerator.class generatorClass);// 默认为AnnotationBeanNameGeneratorscanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :BeanUtils.instantiateClass(generatorClass));// 默认就是扫描包下面的class文件scanner.setResourcePattern(componentScan.getString(resourcePattern));for (AnnotationAttributes filter : componentScan.getAnnotationArray(includeFilters)) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addIncludeFilter(typeFilter);}}for (AnnotationAttributes filter : componentScan.getAnnotationArray(excludeFilters)) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addExcludeFilter(typeFilter);}}boolean lazyInit componentScan.getBoolean(lazyInit);if (lazyInit) {scanner.getBeanDefinitionDefaults().setLazyInit(true);}SetString basePackages new LinkedHashSet();String[] basePackagesArray componentScan.getStringArray(basePackages);for (String pkg : basePackagesArray) {String[] tokenized StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);Collections.addAll(basePackages, tokenized);}for (Class? clazz : componentScan.getClassArray(basePackageClasses)) {basePackages.add(ClassUtils.getPackageName(clazz));}if (basePackages.isEmpty()) {basePackages.add(ClassUtils.getPackageName(declaringClass));}scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {Overrideprotected boolean matchClassName(String className) {// 排除掉自己return declaringClass.equals(className);}});// 开始扫描注册beanreturn scanner.doScan(StringUtils.toStringArray(basePackages));}以上就是如何解析ComponentScan的逻辑解析完后开始扫描进行BeanDefinition注册注意是BeanDefinition注册还不是实例化bean
ClassPathBeanDefinitionScanner#doScanClassPathBeanDefinitionScanner#registerBeanDefinitionBeanDefinitionReaderUtils#registerBeanDefinitionDefaultListableBeanFactory#registerBeanDefinition
最终存放在 beanDefinitionMap beanDefinitionNames 记住这两个属性特别重要
private final MapString, BeanDefinition beanDefinitionMap new ConcurrentHashMap(256);
private volatile List beanDefinitionNames new ArrayList(256);
以上就是通过ComponentScan注解注册Bean的逻辑了其它配置类以及实例化bean的逻辑后面文章在介绍 欢迎关注学习不迷路
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81736.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!