当前位置: 首页 > news >正文

音乐网站怎么做精准关键词昆山品牌网站建设

音乐网站怎么做精准关键词,昆山品牌网站建设,台州做网站的公司,WordPress使用微博外链前言 上一章我们分析了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法的源码逻辑#xff0c;其中核心逻辑do while中调用parser.parse(candidates)方法#xff0c;解析candidates中的候选配置类。然后本章我们主要分析ConfigurationClassParser的…前言 上一章我们分析了ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法的源码逻辑其中核心逻辑do while中调用parser.parse(candidates)方法解析candidates中的候选配置类。然后本章我们主要分析ConfigurationClassParser的parse方法到底做了什么。 parse configCandidates在项目启动的时候只有我们的AopConfig类也就是说这个parse方法其实就是解析启动类。 public void parse(SetBeanDefinitionHolder configCandidates) {for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd holder.getBeanDefinition();try {if (bd instanceof AnnotatedBeanDefinition) {parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());}else if (bd instanceof AbstractBeanDefinition ((AbstractBeanDefinition) bd).hasBeanClass()) {parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());}else {parse(bd.getBeanClassName(), holder.getBeanName());}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException(Failed to parse configuration class [ bd.getBeanClassName() ], ex);}}this.deferredImportSelectorHandler.process();}当前我的启动类是AopConfig属于AnnotatedBeanDefinition会进入到第一个if逻辑里。parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());第一个参数传入的元数据第二个参数传入的是beanName。 private static final PredicateString DEFAULT_EXCLUSION_FILTER className -(className.startsWith(java.lang.annotation.) || className.startsWith(org.springframework.stereotype.));protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);}processConfigurationClass方法传递了一个ConfigurationClass和一个PredicatePredicate就是为了判断ClassName的ConfigurationClass包含了元数据、beanName等信息。 processConfigurationClass 进入方法的第一个if用于判断是否包含Condition注解反正含义就是看这个候选配置类需不需要跳过里面的其他逻辑就不关注了。下面其实就是核心逻辑了我们继续拆解分析。 protected void processConfigurationClass(ConfigurationClass configClass, PredicateString filter) throws IOException {if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;}// 查看这个配置类是不是存在了如果存在就走下面的if逻辑ConfigurationClass existingClass this.configurationClasses.get(configClass);if (existingClass ! null) {if (configClass.isImported()) {if (existingClass.isImported()) {existingClass.mergeImportedBy(configClass);}// Otherwise ignore new imported config class; existing non-imported class overrides it.return;}else {// Explicit bean definition found, probably replacing an import.// Lets remove the old one and go with the new one.this.configurationClasses.remove(configClass);this.knownSuperclasses.values().removeIf(configClass::equals);}}// Recursively process the configuration class and its superclass hierarchy.SourceClass sourceClass asSourceClass(configClass, filter);// 此处使用了个do whiledo {// 查看源码就是习惯性的查看do something开头的至少spring是这样的一个习惯。sourceClass doProcessConfigurationClass(configClass, sourceClass, filter);}while (sourceClass ! null);// 解析完了放入configurationClassesthis.configurationClasses.put(configClass, configClass);}existingClass是看配置类是不是已经解析过了为什么启动的时候要判断是否存在原因就是因为底下有个do while循环。这个方法后续会调用很多次。如果不存在会走底下的do while逻辑就是本章的核心内容。这里会很绕我尽量讲清楚。 SourceClass sourceClass asSourceClass(configClass, filter);还是可以单独拿出来描述一下: 方法的参数包括一个可为null的className和一个PredicateString类型的filter还可能抛出IOException异常。 方法的执行逻辑如下 1、首先检查className是否为null或者经过filter筛选后返回true。如果是这种情况直接返回预先设定的objectSourceClass对象。 2、如果className以java开头表示该类是核心Java类型将不使用ASMJava字节码操作库进行处理。此时尝试加载该类并使用ClassUtils.forName方法获取类的Class对象。如果加载失败将抛出ClassNotFoundException异常并包装为NestedIOException。 3、如果以上条件都不满足说明className表示的类不是核心Java类型那么使用metadataReaderFactory可能是一个元数据读取工厂获取className对应的元数据读取器MetadataReader并将其传递给SourceClass的构造函数创建一个新的SourceClass对象。 doProcessConfigurationClass 首先我的AopConfig有两个注解EnableAspectJAutoProxy和ComponentScan(value {“com.qhyu.cloud.**”})当然我们的springboot项目一般都是约定大于配置的方式不写这个ComponentScan注解。 下面是整个方法的源码和我的个人注释信息我们这边还是先将源码整体放出来然后再拆解分析。 protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, PredicateString filter)throws IOException {// 如果这个候选配置类中有Component注解走下面的逻辑if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass, filter);}// Process any PropertySource annotationsfor (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if (this.environment instanceof ConfigurableEnvironment) {processPropertySource(propertySource);}else {logger.info(Ignoring PropertySource annotation on [ sourceClass.getMetadata().getClassName() ]. Reason: Environment must implement ConfigurableEnvironment);}}// Process any ComponentScan annotations// 我们的AopConfig候选配置类就会走到下面这个逻辑SetAnnotationAttributes componentScans AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);// componentScans不为空第一个条件满足// sourceClass.getMetadata()不为null通过Conditional注解来控制bean是否需要注册控制被Configuration标注的配置类是否需要被解析 第二个条件false取反。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 immediately// 使用this.componentScanParser ComponentScanAnnotationParser来解析// 这里面将会注册我们自己写的一些将被spring接管的类的BeanDefinition信息SetBeanDefinitionHolder 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());}}}}// Process any Import annotationsprocessImports(configClass, sourceClass, getImports(sourceClass), filter, true);// Process any ImportResource annotationsAnnotationAttributes importResource AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);if (importResource ! null) {String[] resources importResource.getStringArray(locations);Class? extends BeanDefinitionReader readerClass importResource.getClass(reader);for (String resource : resources) {String resolvedResource this.environment.resolveRequiredPlaceholders(resource);configClass.addImportedResource(resolvedResource, readerClass);}}// Process individual Bean methodsSetMethodMetadata beanMethods retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// Process default methods on interfacesprocessInterfaces(configClass, sourceClass);// Process superclass, if anyif (sourceClass.getMetadata().hasSuperClass()) {String superclass sourceClass.getMetadata().getSuperClassName();if (superclass ! null !superclass.startsWith(java) !this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturn sourceClass.getSuperClass();}}// No superclass - processing is completereturn null;}片段一 if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass, filter);}当前AopConfig启动类是没有Component注解的不会进入这个逻辑。代码中的英文注释说的是首先递归处理任何成员嵌套类也就是说如果Component注解注释的类中没有内部类嵌套类也不会做任何处理。 片段二 // Process any PropertySource annotationsfor (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if (this.environment instanceof ConfigurableEnvironment) {processPropertySource(propertySource);}else {logger.info(Ignoring PropertySource annotation on [ sourceClass.getMetadata().getClassName() ]. Reason: Environment must implement ConfigurableEnvironment);}}直接看注释处理任何被PropertySource注解修饰的class 片段三 // Process any ComponentScan annotations// 我们的AopConfig候选配置类就会走到下面这个逻辑SetAnnotationAttributes componentScans AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);// componentScans不为空第一个条件满足// sourceClass.getMetadata()不为null通过Conditional注解来控制bean是否需要注册控制被Configuration标注的配置类是否需要被解析 第二个条件false取反。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 immediately// 使用this.componentScanParser ComponentScanAnnotationParser来解析// 这里面将会注册我们自己写的一些将被spring接管的类的BeanDefinition信息SetBeanDefinitionHolder 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());}}}}处理任何被ComponentScan注解修时的类当然这里还包括ComponentScans注解componentScans属性会获取到注解的信息如下图所示 if (!componentScans.isEmpty() !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN))首先componentScans属性肯定不为空所以第一个条件是ture然后看是否应该跳过当前AopConfig不存在Condition注解返回false此处取反所以if条件返回true进入if逻辑。 for (AnnotationAttributes componentScan : componentScans) {// The config class is annotated with ComponentScan - perform the scan immediately// 使用this.componentScanParser ComponentScanAnnotationParser来解析// 这里面将会注册我们自己写的一些将被spring接管的类的BeanDefinition信息SetBeanDefinitionHolder 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());}}}这个循环获取的AnnotaionAttributes就是我们的ComponentScan(value {“com.qhyu.cloud.**”})注解的信息。然后会调用使用this.componentScanParser ComponentScanAnnotationParser来解析主要就是扫描我们定义的路径下的所有需要被Spring管理的bean组装程BeanDefinitionHolder返回到scannedBeanDefinitions集合同时这些bean的定义信息会被注入到bean工厂中本章在此处不会深入的去分析里面的源码将在下一章节进行分析。 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {parse(bdCand.getBeanClassName(), holder.getBeanName());}这段源码在之前已经分析过了第二章节如果发现我们scannedBeanDefinitions中还存在配置类就继续解析也就是把这些beanDefinition都注册到bean工厂中。 如果不是配置类或者处理完了配置类之后会继续往下走他的逻辑。 片段四 处理被Import注解修时的类 processImports(configClass, sourceClass, getImports(sourceClass), filter, true);比如我们的AopConfig不是有个EnableAspectJAutoProxy注解嘛这个注解里面会有个Import所以AopConfig解析之后会执行configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());代码在ConfigurationClassPostProcessor的processConfigBeanDefinitions方法中this.reader.loadBeanDefinitions(configClasses);这行代码会读取出来进行注册。 片段五 处理任何ImportResource annotations // Process any ImportResource annotations AnnotationAttributes importResource AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource ! null) {String[] resources importResource.getStringArray(locations);Class? extends BeanDefinitionReader readerClass importResource.getClass(reader);for (String resource : resources) {String resolvedResource this.environment.resolveRequiredPlaceholders(resource);configClass.addImportedResource(resolvedResource, readerClass);} }片段六 处理各个Bean的方法 // Process individual Bean methods SetMethodMetadata beanMethods retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}片段七 处理接口上的默认方法 processInterfaces(configClass, sourceClass);片段八 处理superclass超类如果有的话。可以发现这里面有个return其他的片段都是返回的void此处如果返回的话外部的do while就会继续执行。 if (sourceClass.getMetadata().hasSuperClass()) {String superclass sourceClass.getMetadata().getSuperClassName();if (superclass ! null !superclass.startsWith(java) !this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturn sourceClass.getSuperClass();} }整理流程梳理 方法的执行逻辑如下 首先检查配置类 configClass 是否被 Component 注解标记。如果是则递归处理任何成员类嵌套类。 处理任何 PropertySource 注解。遍历配置类中的 PropertySource 注解如果当前环境实现了 ConfigurableEnvironment 接口则进行属性源的处理。否则记录日志表明忽略该注解。 处理任何 ComponentScan 注解。获取配置类中的 ComponentScan 注解如果存在且满足相关条件componentScans 不为空且配置类满足条件判断则使用 componentScanParser 来解析注解执行组件扫描操作并注册相应的 BeanDefinition 信息。如果扫描到的定义中包含其他配置类则递归解析这些配置类。 处理任何 Import 注解。根据配置类中的 Import 注解获取需要导入的类并进行处理。这些导入的类可以是其他配置类也可以是其他普通的类。处理过程中可能会继续递归解析导入的类。 处理任何 ImportResource 注解。根据配置类中的 ImportResource 注解获取资源的位置和读取器类型并进行处理。通常这些资源是 XML 配置文件。解析过程中可能会使用 BeanDefinitionReader 来读取并注册相关的 BeanDefinition。 处理配置类中的每个 Bean 方法。获取配置类中所有的 Bean 方法的元数据并将其添加到 configClass 对象中。 处理接口的默认方法。如果配置类实现了接口并且接口中定义了默认方法则对这些默认方法进行处理。 处理父类如果存在。如果配置类有父类并且父类不是 Java 核心类也不在已知的父类列表中则将父类添加到已知的父类列表中并返回父类的注解元数据以便进行递归处理。 如果没有父类则处理完成返回 null。 总结 本章主要分析了ConfigurationClassParser的parse方法的源码其中设计到的ComponentScanAnnotationParser的parse方法我们没有深入分析这里面涉及到的是将我们启动类目录或者ComponentScan注解的basePackages目录下的我们需要交给容器管理的bean的定义信息注册将在下一章进行分析。
http://www.dnsts.com.cn/news/222669.html

相关文章:

  • 拼团购物网站怎么做涉县企业做网站推广
  • 服务器网站后台登陆密码黄框显示商城网站建设咨询
  • 商业网站和企业网站的区别网站建设入门基础
  • 中学生做网站网站重新建设的申请书
  • 新手如何建立自己网站企业网络部署方案
  • 青岛高创网站建设微信小程序公众号开发
  • 公交公司网站建设的意义企业网易邮箱登录入口官网
  • 网站建设成本计划百度信息流开户多少钱
  • 阿里巴巴运营的工作内容html搜索引擎优化
  • 高境网站建设网络营销策略分析
  • 图书管理系统网站开发教程网站制作要钱吗
  • dw制作asp网站模板下载crm客户管理系统的功能有哪些
  • 做网站到哪里做百度云服务器做asp网站
  • 东莞阿里网站设计导航类的wordpress
  • 养老网站建设 中企动力crm客户管理软件平台
  • 手机自己做网站吗做临时网站
  • 资讯网站的优势旅游网站建设计划书
  • 企业网站功能介绍百度竞价广告投放
  • 背景色搭配网站阿里云开发者社区
  • 俄罗斯做电商网站小程序商城开发北京
  • dede网站源码打包下载微商软件商城24小时
  • 网站开发技术人员手机网站欢迎页面设计
  • 建站优化系统人人设计网网址
  • 青海 网站开发 app gis网站如何做rss订阅
  • 新公司 做网站 流程安卓市场2021最新版下载
  • 鞍山做网站的公司贵州省住房和城乡建设官方网站
  • 东莞网站建设网页推广网上购物网站开发英文文献
  • 为什么网站不建议做充值功能网站空间有什么用
  • 网站发布系统山东省住建厅官网二建查询
  • 潍坊网站建设尚荣深圳建网站技术