游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

盘点SpringConditional

  一。前言
  这一篇来看一下Conditional的使用和原理,先来看一下整体的体系结构
  二。使用ConditionalOnBean:当容器里有指定Bean的条件下。ConditionalOnMissingBean:当容器里没有指定Bean的情况下。ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但是指定首选BeanConditionalOnClass:当类路径下有指定类的条件下。ConditionalOnMissingClass:当类路径下没有指定类的条件下。ConditionalOnProperty:指定的属性是否有指定的值ConditionalOnResource:类路径是否有指定的值ConditionalOnExpression:基于SpEL表达式作为判断条件。ConditionalOnJava:基于Java版本作为判断条件ConditionalOnJndi:在JNDI存在的条件下差在指定的位置ConditionalOnNotWebApplication:当前项目不是Web项目的条件下ConditionalOnWebApplication:当前项目是Web项目的条件下2。1基础使用2。2自定义ConditionalpublicclassDefaultConditionalimplementsCondition{privateLoggerloggerLoggerFactory。getLogger(this。getClass());Overridepublicbooleanmatches(ConditionContextcontext,AnnotatedTypeMetadatametadata){logger。info(进行Conditional判断);returnfalse;}}2。3基础使用BeanConditionalOnBean(TestService。class)publicConfigBeangetConfigBean(){logger。info(开始加载ConditionalOnBean);returnnewConfigBean();}三。自定义原理分析3。1Conditional入口
  对于Configuration。Bean的创建方式,Conditinal的起点是refushinvokeBeanFactoryPostProcessors,在其中会调用ConfigurationClassPostProcessor进行处理privatevoidloadBeanDefinitionsForBeanMethod(BeanMethodbeanMethod){Step1:获取当前Configuration中Bean的元数据信息ConfigurationClassconfigClassbeanMethod。getConfigurationClass();MethodMetadatametadatabeanMethod。getMetadata();StringmethodNamemetadata。getMethodName();判断是否应该跳过当前Beanif(this。conditionEvaluator。shouldSkip(metadata,ConfigurationPhase。REGISTERBEAN)){configClass。skippedBeanMethods。add(methodName);return;}if(configClass。skippedBeanMethods。contains(methodName)){return;}}3。2Conditional判断的流程
  ConditionEvaluator是核心处理类,最终都会调用shouldSkip判断是否跳过CConditionEvaluatorpublicbooleanshouldSkip(NullableAnnotatedTypeMetadatametadata,NullableConfigurationPhasephase){Step1:如果当前Bean不包含Conditional,则直接返回if(metadatanull!metadata。isAnnotated(Conditional。class。getName())){returnfalse;}Step2:有2种ConfigurationPhase的类型,表示2种配置的阶段PARSECONFIGURATION:Condition应该在解析Configuration类时进行计算,如果此时条件不匹配,则不会添加Configuration类REGISTERBEAN:条件不会阻止Configuration类被添加,在评估条件时,所有Configuration类都将被解析if(phasenull){if(metadatainstanceofAnnotationMetadataConfigurationClassUtils。isConfigurationCandidate((AnnotationMetadata)metadata)){returnshouldSkip(metadata,ConfigurationPhase。PARSECONFIGURATION);}returnshouldSkip(metadata,ConfigurationPhase。REGISTERBEAN);}Step3:获取所有的Condition对象ListConditionconditionsnewArrayList();for(String〔〕conditionClasses:getConditionClasses(metadata)){for(StringconditionClass:conditionClasses){ConditionconditiongetCondition(conditionClass,this。context。getClassLoader());conditions。add(condition);}}Step4:排序AnnotationAwareOrderComparator。sort(conditions);for(Conditioncondition:conditions){ConfigurationPhaserequiredPhasenull;if(conditioninstanceofConfigurationCondition){requiredPhase((ConfigurationCondition)condition)。getConfigurationPhase();}Step5:最终的Condition匹配过程if((requiredPhasenullrequiredPhasephase)!condition。matches(this。context,metadata)){returntrue;}}returnfalse;}
  直到这里就开始匹配到对应的方法四。常规加载方式
  解析
  已知的Conditional是基于SpringBootCondition实现的,其具体抽象类为FilteringSpringBootCondition,看一下主要的继承关系
  去除不需要配置的类
  第一步是快速去除不需要的类,主要流程如下:起点:AbstractApplicationContextrefreshinvokeBeanFactoryPostProcessors处理:ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry处理主要逻辑拦截:ConfigurationClassFilterfilter匹配:FilteringSpringBootConditionmatch
  注意,这里是进行match匹配,目的是获取基于正在导入的Configuration类的AnnotationMetadata的AutoConfigurationEntry4。1Filter拦截
  Filter拦截是在ConfigurationClassFilter,其中会对所有的Conditional进行拦截处理privatestaticclassConfigurationClassFilter{自动配置的元数据privatefinalAutoConfigurationMetadataautoConfigurationMetadata;ListStringfilter(ListStringconfigurations){longstartTimeSystem。nanoTime();此处为所有的Confiturations类String〔〕candidatesStringUtils。toStringArray(configurations);booleanskippedfalse;此处包含OnBeanCondition,OnClassCondition,OnWebApplicationCondition三种for(AutoConfigurationImportFilterfilter:this。filters){获取是否存在match匹配boolean〔〕matchfilter。match(candidates,this。autoConfigurationMetadata);for(inti0;imatch。length;i){if(!match〔i〕){candidates〔i〕null;skippedtrue;}}}if(!skipped){returnconfigurations;}如果不能跳过,记录当前Confiturations类ListStringresultnewArrayList(candidates。length);for(Stringcandidate:candidates){if(candidate!null){result。add(candidate);}}returnresult;}}4。2FilteringSpringBootCondition中match匹配
  此处是重写了其父类的match方法publicboolean〔〕match(String〔〕autoConfigurationClasses,AutoConfigurationMetadataautoConfigurationMetadata){Step1:准备Report对象,用于记录ConditionEvaluationReportreportConditionEvaluationReport。find(this。beanFactory);Step2:获取对应的所有的Condition方法ConditionOutcome〔〕outcomesgetOutcomes(autoConfigurationClasses,autoConfigurationMetadata);boolean〔〕matchnewboolean〔outcomes。length〕;for(inti0;ioutcomes。length;i){对match中的数组进行赋值,当outcomes对应下标的ConditionOutcome匹配时为true。其他情况,返回falsematch〔i〕(outcomes〔i〕nulloutcomes〔i〕。isMatch());if(!match〔i〕outcomes〔i〕!null){记录日志logOutcome(autoConfigurationClasses〔i〕,outcomes〔i〕);if(report!null){像ConditionEvaluationReportSortedMap存放评估条件report。recordConditionEvaluation(autoConfigurationClasses〔i〕,this,outcomes〔i〕);}}}returnmatch;}
  ConditionEvaluationReport的作用
  该对象用来记录自动化配置过程中条件匹配的详细信息及日志信息publicfinalclassConditionEvaluationReport{bean名称privatestaticfinalStringBEANNAMEautoConfigurationReport;创建一个父的条件匹配对象privatestaticfinalAncestorsMatchedConditionANCESTORCONDITIONnewAncestorsMatchedCondition();存放类名或方法名(key),条件评估输出对象(value)privatefinalSortedMapString,ConditionAndOutcomesoutcomesnewTreeMap();是否是原始条件匹配对象privatebooleanaddedAncestorOutcomes;父的条件评估报告对象privateConditionEvaluationReportparent;记录已经从条件评估中排除的类名称privatefinalListStringexclusionsnewArrayList();记录作为条件评估的候选类名称privatefinalSetStringunconditionalClassesnewHashSet();}4。3getOutcomes获取
  此处以OnBean为例,此处存在一定的关联关系:protectedfinalConditionOutcome〔〕getOutcomes(String〔〕autoConfigurationClasses,AutoConfigurationMetadataautoConfigurationMetadata){Step1:初始化一个和处理类等容量的数组ConditionOutcome〔〕outcomesnewConditionOutcome〔autoConfigurationClasses。length〕;Step2:遍历所有的autoConfigurationClassesfor(inti0;ioutcomes。length;i){StringautoConfigurationClassautoConfigurationClasses〔i〕;if(autoConfigurationClass!null){SetStringonBeanTypesautoConfigurationMetadata。getSet(autoConfigurationClass,ConditionalOnBean);判断是否存在ConditionalOnBean标注的方法outcomes〔i〕getOutcome(onBeanTypes,ConditionalOnBean。class);判断是否需要输出ConditionOutcomeif(outcomes〔i〕null){SetStringonSingleCandidateTypesautoConfigurationMetadata。getSet(autoConfigurationClass,ConditionalOnSingleCandidate);此处是返回是否要处理outcomes〔i〕getOutcome(onSingleCandidateTypes,ConditionalOnSingleCandidate。class);}}}returnoutcomes;}4。4如何判断是否符合评估条件
  注意,这里的matches和FilteringSpringBootCondition不是一个FilteringSpringBootConditionmatch:基于AutoConfigurationImportFilter,对给定的自动配置类候选应用筛选器SpringBootConditionmatches:需要返回最终的判断结果
  调用流程在loadBeanDefinitionsForBeanMethod等类似流程种调用shouldSkip,从而跳转到该逻辑Overridepublicfinalbooleanmatches(ConditionContextcontext,AnnotatedTypeMetadatametadata){获取注解对应的方法名或者类名StringclassOrMethodNamegetClassOrMethodName(metadata);try{获取对应的条件匹配类,此处会判断metadatainstanceof,有限判断是否为ClassMetadataConditionOutcomeoutcomegetMatchOutcome(context,metadata);很简单的打印日志,Trace级别logOutcome(classOrMethodName,outcome);记录结果,通过ConditionEvaluationReport和recordEvaluation方法实现recordEvaluation(context,classOrMethodName,outcome);返回是否成功匹配returnoutcome。isMatch();}catch(NoClassDefFoundErrorex){thrownewIllegalStateException(。。。。。。);}catch(RuntimeExceptionex){thrownewIllegalStateException(ErrorprocessingconditionongetName(metadata),ex);}}
  这里的核心就是调用getMatchOutcome判断是否符合或者不符合要求,getMatchOutcome需要子类重写五。getMatchOutcome详情5。1OnClasspublicConditionOutcomegetMatchOutcome(ConditionContextcontext,AnnotatedTypeMetadatametadata){Step1:获取当前容器ClassLoaderClassLoaderclassLoadercontext。getClassLoader();ConditionMessagematchMessageConditionMessage。empty();Step2:判断是否有ConditionalOnClass约束ListStringonClassesgetCandidates(metadata,ConditionalOnClass。class);if(onClasses!null){Step21:filter过滤,判断是否缺失类ListStringmissingfilter(onClasses,ClassNameFilter。MISSING,classLoader);if(!missing。isEmpty()){returnConditionOutcome。noMatch(ConditionMessage。forCondition(ConditionalOnClass。class)。didNotFind(requiredclass,requiredclasses)。items(Style。QUOTE,missing));}Step22:构建matchMessagematchMessagematchMessage。andCondition(ConditionalOnClass。class)。found(requiredclass,requiredclasses)。items(Style。QUOTE,filter(onClasses,ClassNameFilter。PRESENT,classLoader));}Step3:同理,判断是否需要MissClassesListStringonMissingClassesgetCandidates(metadata,ConditionalOnMissingClass。class);if(onMissingClasses!null){。。。。与ConditionalOnClass基本类似,此处省略}returnConditionOutcome。match(matchMessage);}
  补充:ConditionMessage的作用5。2OnBean
  与OnBean类似,这里就展示一种publicConditionOutcomegetMatchOutcome(ConditionContextcontext,AnnotatedTypeMetadatametadata){ConditionMessagematchMessageConditionMessage。empty();MergedAnnotationsannotationsmetadata。getAnnotations();if(annotations。isPresent(ConditionalOnBean。class)){Step1:获取ConditionalOnBean注解信息SpecConditionalOnBeanspecnewSpec(context,metadata,annotations,ConditionalOnBean。class);Step2:返回匹配结果其内部通过getNamesOfBeansIgnoredByType,getBeanNamesForType等方式判断类是否存在MatchResultmatchResultgetMatchingBeans(context,spec);if(!matchResult。isAllMatched()){StringreasoncreateOnBeanNoMatchReason(matchResult);returnConditionOutcome。noMatch(spec。message()。because(reason));}matchMessagespec。message(matchMessage)。found(bean,beans)。items(Style。QUOTE,matchResult。getNamesOfAllMatches());}if(metadata。isAnnotated(ConditionalOnSingleCandidate。class。getName())){。。。。。}if(metadata。isAnnotated(ConditionalOnMissingBean。class。getName())){。。。。。}returnConditionOutcome。match(matchMessage);}总结
  Conditional本身并不难,这一篇主要是为了完善图谱以及后续的starter启动流程方案做准备。
  整个流程中有几个环节理解就行了:Spring中的Conditional都会继承SpringBootCondition,会实现其getOutcomes方法getOutcomes是用于快速去掉无需加载的Configuration,getMatchOutcome是为了验证匹配关系通常都会通过ConditionEvaluator的shouldSkip判断是否需要跳过Bean流程

PS5销量突破1000万台成索尼史上销售最快的主机来源:TechWeb。com。cn作者:Suky【TechWeb】索尼官方近日宣布,新一代游戏主机PlayStation5自2020年11月12日首度问世以来,全球销量已……老美的危机感,得电池者得汽车智造未来,我们正在主导锂电供应链汽车工业在国家经济格局中,起着重要支柱作用。在过去的几十年,汽车制造几乎是西方发达国家工业实力的象征。近两年,汽车行业面临着革命性的转型,开始进入电动化和智能化时代。咨询……北京昌平第一富豪打造高端医疗器械龙头企业,身家115亿北京昌平首富:打造高端医疗器械龙头企业,如今身家百亿推荐语:昌平区,隶属于北京市,位于北京西北部,此地风景秀美,其中的小汤山就是全国知名的温泉旅游胜地。值得一提的是……RedmiAirDots3Pro300元内真无线降噪耳机的焊Intro:你敢相信吗?有款蓝牙耳机有着和AppleAirPodsPro同等级的主动降噪,比AirPodsPro更低的延迟和更长的续航,却只须花AirPodsPro16的……文具也内卷?探访最大的文具市场黑科技文具惊艳家长8月30日,即将迎来一年一度的开学季,走进石家庄最大的文具批发市场,随处可见黑科技文具。南有义乌,北有南三条。地处石家庄中心商业繁华区的南三条,是北方地区最大的小商品集散……马化腾害人不浅!!网络游戏毒害中国整整一代人,坚决抵制游戏!大家好!我是一个高中生的父母,家里开着一个不大不小的店,赚的钱也不多,儿子和很多高中生一样都爱玩游戏,但是自从上了高中,儿子一回到家就是玩那些手机游戏什么王者荣耀,和平精英这些……工信部亮明态度,将推动钠离子电池全面商业化电车汇消息:今日,工信部发布了一份政协提案答复函,答复函称,有关部门将组织有关标准研究机构适时开展钠离子电池标准制定,并在标准立项、标准报批等环节予以支持。将支持钠离子电池加速……三星S10发布性能和小米9相比,买谁似乎有答案了!距离小米9发布已经过去一周了,本周二小米9第一次开抢,不知道有多多少小伙伴在这53秒内抢购成功,当然这次没有买到小米9的同学不要灰心,小米9和RedmiNote7销售方式不一样……学计算机专业当程序员?现在也没那么容易了回想很多很多年以前,学好C语言就能找到一份好工作,不论你是中专毕业,还是本科毕业;不论你是全日制学学习,还是北大青鸟,达内等教培机构半路出家;总之,你只要会一些,你就能谋到一份……USGFX指控清算人冻结其澳洲以外银行账户近日,零售外汇及差价合约经纪商USG联准国际集团瓦鲁阿图公司表示,该公司ASIC监管主体USG澳大利亚子公司的清算人BRIFerrier试图冻结没收澳大利亚以外的资产。2……威高骨科上市,青岛淄博潍坊首富纷纷拟添第二股,济南首富更波折文丛树来源鲁商儒风一家公司已经承载不了山东各地首富们的梦想了。青岛的国恩股份以3亿元收购创业板上市公司东宝生物,成为控股股东;威海的威高骨科在科创板上市;淄博……国产手机有多强?7年的OPPO还被山寨,连抄袭金立都卖得比苹如果把时间往回拨10年,那时候市面上喊话最疯狂的应该就是:大、薄、清、强!超豪华3G智能手机!外面卖5888,我们只要399元!赶紧拨打电话订购吧!不知道大家还有没有印象……
白蛇缘起首周末口碑超高获得史上国漫最高分星关系1月14日讯由追光动画、华纳兄弟共同出品的2019首部成人向国漫《白蛇:缘起》已经在1月11日在全国上映。猫眼9。4分、淘票票9。2分的成绩强势领跑同档期影片,在猫眼更是……这座钢铁巨兽竟然高过迪拜塔掠食城市巅峰打造未来城市奇观由执导过《指环王》《霍比特人》系列的导演彼得杰克逊打造的全新科幻史诗巨制《掠食城市》今日发布钢铁巨兽版预告,彼得杰克逊惊喜亮相,为观众带来呕心沥血打造的未来伦敦城。作为片中最大……成就国漫历史最高分!白蛇缘起彩蛋露真容引发回忆杀星关系1月13日讯由追光动画、华纳兄弟联合出品的国漫爱情力作《白蛇:缘起》曝光断桥彩蛋,引发无数观众回忆。这部历时三年制作的高品质动画佳作一经上映便引发观影热潮,让沉寂了一段时……掠食城市惊现3000米空中卡萨布兰卡全息影像打造恢宏奇观星关系1月12日讯由执导过《指环王》《霍比特人》系列的导演彼得杰克逊打造的全新科幻史诗巨制《掠食城市》今日发布云中要塞预告,杰克逊亲自揭秘漂浮于3000米高空的云中之城空港。这……白蛇缘起发口碑特辑观众大赞它值得给满分由追光动画、华纳兄弟联合出品的魔幻爱情动画电影《白蛇:缘起》已于昨日在全国正式开画,今日影片曝出一支口碑特辑,特辑中收录了许多观众在看完电影后给出的精彩评论。影片自点映以来,收……沙出重维纪录片京新大穿越上线沙宝亮以歌会英雄星关系1月11日讯继《沙出重维》纪录片之哈雷兄弟篇上线后,京新大穿越也于今日正式上线。这部纪录片中沙宝亮以歌会友,和好友们一起穿越G7京新公路沙漠无人区,解锁新技能。纪录……电影家和万事惊预售开启首支口碑特辑曝光引人深思星关系1月11日讯由著名导演邱礼涛执导,吴镇宇、古天乐、袁咏仪、张达明领衔主演,吴肇轩、蔡颂思、林雪、林子聪、李璨琛、孔令令等演员倾力出演的国民荒诞喜剧《家和万事惊》自全国观影……老实之人可来往,温和之人可交谈,沉稳之人可共事到底怎样才算是老实人呢?当然不是那些庸庸碌碌、无能无为的人,而是那些老老实实做人、踏踏实实干事、兢兢业业工作的人;就是始终勇于挑重担,敢于打硬仗的人。只有同这些来往,我们才能有……亚裔攻气女王杀到好莱坞智海演绎掠食城市铁骨柔情女英雄星关系1月11日讯由执导过《指环王》《霍比特人》系列的导演彼得杰克逊全新打造的科幻史诗巨制《掠食城市》今日发布冷酷女王角色特辑,彼得杰克逊与安娜方的饰演者智海亮相特辑,为观众解……开年悬疑大作22年后的自白今日公映五大超级看点全揭秘电影《22年后的自白》今日内地正式公映,这部被网友评为2019开年悬疑大作的日本电影,是继《看不见的客人》之后,又一部口碑甚佳的外国悬疑片。该片自定档以来就获得了影评人、悬疑片……红星美凯龙的高端局,能助其突破负债瓶颈期吗?高端智能电器主题馆,是老年红星美凯龙打破瓶颈期的密匙?十月前夕,建材家居行业老大的红星美凯龙在郑州开业全球最大的智能电器至尊馆,总面积高达2。6万方;而在这之前,其已在全……神探蒲松龄曝全阵容海报成龙加群星陪你欢度大年星关系1月10日讯定档于2019大年初一上映的奇幻贺岁大片《神探蒲松龄》,近日发布全阵容海报,正式曝光影片豪华的全明星阵容,海报中成龙、阮经天、钟楚曦、林柏宏、林鹏、乔杉、潘长……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网