温州中豪网站建设推广全国最大房产网络平台

web/2025/10/7 11:41:37/文章来源:
温州中豪网站建设推广,全国最大房产网络平台,用开源源码做淘宝客网站,合肥房产备案网上查询简介 前面介绍了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/88452.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深圳市盐田区住房和建设局网站正安县网站seo优化排名

文章目录题目描述解析代码题目描述 解析 第一感觉:啥都没感觉出来。。。 直接拿动态规划高精做的 但是只能拿40 重新分析一下这道题: g(x)首先可以拿快速幂很容易的求出来 问题就转化为了**把g(x)个东西分成k份的方案数 其实答案…

网站推广推广WordPress显示403

初涉的话先留坑吧 题目大意 $\sum_{i_1}^{a_1}\sum_{i_2}^{a_2}\cdots\sum_{i_m}^{a_m}(i_1,i_2,\cdots,i_m)$ $a_i<1e6,2<m<10$ 题目分析 首先寄存两篇比较好的博客&#xff1a; 1.铃悬的数学小讲堂——狄利克雷卷积与莫比乌斯反演 2.[学习笔记]莫比乌斯反演常见模型…

php 企业网站模板开发者门户网站是什么意思

1. 竞争市场 1.1. 算法、大数据、超级平台的风起云涌似乎预示了市场竞争机制的加速终结&#xff0c;而我们似乎也对这种市场机制的衰退见怪不怪 1.1.1. 它有效节省了消费者的搜寻成本&#xff0c;降低了市场准入壁垒&#xff0c;开辟了市场扩张与准入之间的崭新通道&#xff…

网站建设的作用和意义中小型企业网搭建

一般用下面的方法可以解决: 1&#xff1a;确认在“配置属性”中的“启用ASP.NET调试"为"True" 2&#xff1a;确认你的"web.config"中的"debugtrue" 3&#xff1a;若你安装过Win2000 SP4后&#xff0c;则要在命令行执行"regsvr32 i asp…

phpwind能做网站吗域名批量注册查询

用HBuider写的Web项目&#xff0c;项目名如果包含中文&#xff0c;edge下无法显示图片转载于:https://www.cnblogs.com/phoenixBlog/p/9964820.html

建网站 xyz汉阳网站推广公司

哪些好用的AI绘画生成软件&#xff1f;随着人工智能技术的飞速发展&#xff0c;AI绘画生成软件逐渐走入大众的视野&#xff0c;为艺术创作领域带来了革命性的变革。今天&#xff0c;就让我们一起探索四款备受推崇的AI绘画生成软件&#xff0c;看看它们如何以独特的魅力&#xf…

网站如何收费企业网站系统功能分析与设计

文章目录 Flutter应用让屏幕在 app 运行期间保持常亮的方法方法一&#xff1a;使用系统插件方法二&#xff1a;使用 Widgets注意事项 Flutter应用让屏幕在 app 运行期间保持常亮的方法 在 Flutter 开发中&#xff0c;可以使用以下两种方法让屏幕在 app 运行期间保持常亮&#…

网站备案 邮寄资料哪个小说网站版权做的好

问题分析子问题界定&#xff1a;由参数 k 和 y 界定k&#xff1a;考虑对物品1, 2, … , k 的选择 y&#xff1a;背包总重量不超过 y 原始输入&#xff1a;k n, y b 子问题计算顺序&#xff1a; k 1, 2, … , n 对于给定的 k&#xff0c;y 1, 2, … , b 定义问题 假设有 n 个…

怎样做淘宝商品链接导航网站古镇做灯饰网站的公司

推荐阅读&#xff1a;我的技术回顾那些与ABP框架有关的故事-2015年从ABP框架国内社区发展回顾.NET技术变迁-2016年从2022年来回顾ABP框架&#xff0c;我们会发现无论是商业模式还是架构设计思路&#xff0c;如果没有良好的商业模式的话&#xff0c;ABP框架很容易进入难产的状态…

js网站页面效果经营类网页游戏大全

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 目录 ✍&#x1f3fb;序言✍&#x1f3fb;1️⃣✍&#x1f3fb;es的架构简介1. 分布式架构2. 索引与搜索3. 数据写入与持久化4. 缓…

电子商务网站建设规划心得旅游网站手机模板

1.安装tomcat docker hub上面查找tomcat镜像 docker search tomcat 从docker hub上拉取tomcat镜像到本地 docker pull tomcat docker images查看是否有拉取到的tomcat 使用tomcat镜像创建容器实例(也叫运行镜像) docker run -it -p 8080:8080 tomcat -p 小写&#xff0c;主…

小程序登录页面合作seo公司

系列博客目录 文章目录 系列博客目录怎么样才能够在简历上写熟悉redisson的应用以及原理1. 清晰描述技能与经验示例&#xff1a; 2. 列举具体应用场景示例项目经验&#xff1a; 3. 展示你对原理的理解示例&#xff1a; 4. 用简历中的关键词突出你的能力示例段落&#xff1a; 5.…

政务公开 加强门户网站建设企业网站建设变相收取等级保护费6

mockito入门本文是我们名为“ 用Mockito测试 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入了解Mockito的魔力。 您将了解有关“模拟”&#xff0c;“间谍”和“部分模拟”的信息&#xff0c;以及它们相应的存根行为。 您还将看到使用测试双打和对象匹配器进行验证的…

建网360 网站建设电影网站建设多少钱

通用文字识别OCR&#xff1a;多场景、多语种、高精度的整图文字检测和识别服务&#xff0c;多项指标行业领先&#xff0c;可识别中、英、日、韩、法、德多种语言。 企业基本信息API&#xff1a;通过公司名称/公司ID/注册号或社会统一信用代码获取企业基本信息&#xff0c;企业…

网站 数据备份简历设计网站

1.基于java注解实现websocket服务器端 1.1需要的类 1.1.1服务终端类 用java注解来监听连接ServerEndpoint、连接成功OnOpen、连接失败OnClose、收到消息等状态OnMessage 1.1.2配置类 把spring中的ServerEndpointExporter对象注入进来 2.1代码示例 2.1.1 maven配置 <…

怎样建立一个自己的网站如何建设音乐网站

重启您的CentOS系统。 在GRUB引导加载器启动过程中&#xff0c;当看到启动画面时&#xff0c;按下e键进入编辑模式。 找到以 linux16 或 linux 开头的启动行。 在该行的末尾添加 rd.break 或者ro&#xff08;只读&#xff09;修改为 rw 加init/sysroot/bin/sh参数&#xff0…

在线电影网站建设凡科网站怎么做外链

ChatGPT在语义理解和信息提取领域有着广泛的应用潜力。语义理解是指对文本进行深层次的理解&#xff0c;包括词义、句义和篇章义等层面的理解。信息提取是指从文本中自动抽取结构化的信息&#xff0c;如实体、关系、事件等。ChatGPT作为一种预训练语言模型&#xff0c;具有丰富…

重庆sem网站推广渭南做网站电话

启动Unity发布的exe并且添加启动参数 在启动Unity的时候添加一些启动的参数。 代码解释 在启动的时候获取的启动参数如果没有获取到正确的启动参数那么就退出程序&#xff0c;这个代码仅仅在发布到windows之后才会生效&#xff0c;在编辑器下这个代码虽然会获取到参数但是不能…

天津河东做网站贵吗关于校园网站的策划书

目录 一、创建Web页面浏览器 1.示例源码 2.生成效果 二、局域网聊天程序 1.类 2.服务器端 3.客户端 一、创建Web页面浏览器 TextBox 控件用来输入要浏览的网页地址&#xff0c;Button控件用来执行浏览网页操作&#xff0c; WebBrowser控件用来显示要浏览的网页。这个控…

南宁市建设处网站分类模板wordpress

Zipkin是一款开源的分布式链路追踪系统,主要功能包括: 1. 采集跟踪数据 - Zipkin client库负责收集并上报各服务的请求信息。 2. 存储跟踪数据 - 存储层默认采用Zipkin自带的基于内存的快速存储,也支持整合MySQL、Cassandra等外部存储。 3. 查询接口 - 提供RESTful API进行跟…