城市直播房产教育博客汽车
投稿投诉
汽车报价
买车新车
博客专栏
专题精品
教育留学
高考读书
房产家居
彩票视频
直播黑猫
投资微博
城市上海
政务旅游

Spring里面的Import注解到底是个啥?

6月2日 牵手手投稿
  Spring提供了几种方式来注册Bean,日常开发中使用最多的是ComponentScan。得益于ComponentScan,注册bean非常的简单,只需要在被注册的类上声明Component或者Service等注解即可。
  除了ComponentScan,Spring还支持使用Configuration注解来注册Bean。在大型的项目中,模块化开发能极大地降低系统的复杂性,这时需要每个模块来定义本模块Bean注册情况,Configuration发挥着巨大的作用。ConfigurationConditionalOnProperty(prefixmodule。wxlogin,valueenable,havingValuetrue)ComponentScan(basePackagescom。lin。decorator。wxlogin)publicclassWxLoginConfiguration{}
  每个模块定义了Configuration之后,需要将多个模块的Configuration组合。Spring提供了Import注解来实现多个Configuration组合。Import(WxLoginConfiguration。class)publicclassApplication{publicstaticvoidmain(String〔〕args){SpringApplication。run(Application。class,args);}}
  Spring官方文档中关于Import的描述如下:
  ProvidesfunctionalityequivalenttotheelementinSpringXML。AllowsforimportingConfigurationclasses,ImportSelectorandImportBeanDefinitionRegistrarimplementations,aswellasregularcomponentclasses(asof4。2;analogoustoAnnotationConfigApplicationContext。register(java。lang。C?。。。))。
  BeandefinitionsdeclaredinimportedConfigurationclassesshouldbeaccessedbyusingAutowiredinjection。Eitherthebeanitselfcanbeautowired,ortheconfigurationclassinstancedeclaringthebeancanbeautowired。Thelatterapproachallowsforexplicit,IDEfriendlynavigationbetweenConfigurationclassmethods。
  除了Configuration,Import还支持引入ImportSelector和ImportBeanDefinitionRegistrar。既然要全面了解Import机制,那另外两个也要一探究竟。ImportSelector
  Spring官方文档中,对ImportSelector的描述如下:
  InterfacetobeimplementedbytypesthatdeterminewhichConfigurationclass(es)shouldbeimportedbasedonagivenselectioncriteria,usuallyoneormoreannotationattributes。
  从字面上理解,ImportSelector可以根据注解里面的一个或多个属性来决定引入哪些Configuration。举个例子:
  小伙伴都用过Transactional注解,Transactional注解生效的前提是EnableTransactionManagement生效。看过EnableTransactionManagement源代码的小伙伴应该都知道,它通过Import引入了一个ImportSelector。Target(ElementType。TYPE)Retention(RetentionPolicy。RUNTIME)DocumentedImport(TransactionManagementConfigurationSelector。class)publicinterfaceEnableTransactionManagement{booleanproxyTargetClass()AdviceModemode()defaultAdviceMode。PROXY;intorder()defaultOrdered。LOWESTPRECEDENCE;}
  而TransactionManagementConfigurationSelector会根据注解里面的AdviceMode不同,来确定引入不同的Configuration。protectedString〔〕selectImports(AdviceModeadviceMode){switch(adviceMode){casePROXY:returnnewString〔〕{AutoProxyRegistrar。class。getName(),ProxyTransactionManagementConfiguration。class。getName()};caseASPECTJ:returnnewString〔〕{determineTransactionAspectClass()};default:}}ImportBeanDefinitionRegistrar
  Spring官方文档中,对ImportBeanDefinitionRegistrar的描述如下:
  InterfacetobeimplementedbytypesthatregisteradditionalbeandefinitionswhenprocessingConfigurationclasses。Usefulwhenoperatingatthebeandefinitionlevel(asopposedtoBeanmethodinstancelevel)isdesiredornecessary。
  字面意思是,通过继承这个接口可以额外定义Bean。举个例子:
  在使用Mybatis的时候,会使用到MapperScan这个注解,这个注解通过Import引入了ImportBeanDefinitionRegistrar,这也解释了为什么我们只在Interface上申明了一个Mapper,mybatis就帮我们生成好了Bean。Retention(RetentionPolicy。RUNTIME)Target(ElementType。TYPE)DocumentedImport(MapperScannerRegistrar。class)Repeatable(MapperScans。class)publicinterfaceMapperScan{}
  有小伙伴在编码工程中,并没有使用MapperScan,为什么也能正常使用呢?其实是Mybatisstarter的功劳。在MybatisAutoConfiguration里面定义了ImportBeanDefinitionRegistrar,当MapperScan没有激活时,它就会生效。org。springframework。context。annotation。ConfigurationImport(AutoConfiguredMapperScannerRegistrar。class)ConditionalOnMissingBean({MapperFactoryBean。class,MapperScannerConfigurer。class})publicstaticclassMapperScannerRegistrarNotFoundConfigurationimplementsInitializingBean{OverridepublicvoidafterPropertiesSet(){logger。debug(NotfoundconfigurationforregisteringmapperbeanusingMapperScan,MapperFactoryBeanandMapperScannerConfigurer。);}}Import执行流程
  了解了Import支持的三种不同类型的资源之后,接下来通过debug来看一下import的执行过程。通过设置断点,发现在ConfigurationClassParser类中,通过深度遍历来处理Import。privatevoidcollectImports(SourceClasssourceClass,SetSourceClassimports,SetSourceClassvisited)throwsIOException{if(visited。add(sourceClass)){for(SourceClassannotation:sourceClass。getAnnotations()){StringannNameannotation。getMetadata()。getClassName();if(!annName。equals(Import。class。getName())){collectImports(annotation,imports,visited);}}imports。addAll(sourceClass。getAnnotationAttributes(Import。class。getName(),value));}}
  而上面介绍的ImportSelector,需要调用selectImports方法进行解析。privatevoidprocessImports(ConfigurationClassconfigClass,SourceClasscurrentSourceClass,CollectionSourceClassimportCandidates,PredicateStringexclusionFilter,booleancheckForCircularImports){if(importCandidates。isEmpty()){}if(checkForCircularImportsisChainedImportOnStack(configClass)){this。problemReporter。error(newCircularImportProblem(configClass,this。importStack));}else{this。importStack。push(configClass);try{for(SourceClasscandidate:importCandidates){if(candidate。isAssignable(ImportSelector。class)){CandidateclassisanImportSelectordelegatetoittodetermineimportsC?candidateClasscandidate。loadClass();ImportSelectorselectorParserStrategyUtils。instantiateClass(candidateClass,ImportSelector。class,this。environment,this。resourceLoader,this。registry);PredicateStringselectorFilterselector。getExclusionFilter();if(selectorFilter!null){exclusionFilterexclusionFilter。or(selectorFilter);}if(selectorinstanceofDeferredImportSelector){this。deferredImportSelectorHandler。handle(configClass,(DeferredImportSelector)selector);}else{String〔〕importClassNamesselector。selectImports(currentSourceClass。getMetadata());CollectionSourceClassimportSourceClassesasSourceClasses(importClassNames,exclusionFilter);processImports(configClass,currentSourceClass,importSourceClasses,exclusionFilter,false);}}elseif(candidate。isAssignable(ImportBeanDefinitionRegistrar。class)){CandidateclassisanImportBeanDefinitionRegistrardelegatetoittoregisteradditionalbeandefinitionsC?candidateClasscandidate。loadClass();ImportBeanDefinitionRegistrarregistrarParserStrategyUtils。instantiateClass(candidateClass,ImportBeanDefinitionRegistrar。class,this。environment,this。resourceLoader,this。registry);configClass。addImportBeanDefinitionRegistrar(registrar,currentSourceClass。getMetadata());}else{CandidateclassnotanImportSelectororImportBeanDefinitionRegistrarprocessitasanConfigurationclassthis。importStack。registerImport(currentSourceClass。getMetadata(),candidate。getMetadata()。getClassName());processConfigurationClass(candidate。asConfigClass(configClass),exclusionFilter);}}}catch(BeanDefinitionStoreExceptionex){}catch(Throwableex){thrownewBeanDefinitionStoreException(Failedtoprocessimportcandidatesforconfigurationclass〔configClass。getMetadata()。getClassName()〕,ex);}finally{this。importStack。pop();}}}
  通过递归的方式,实现了资源的加载。
  本文基于Spring5。3。4,如有错误,欢迎指正。
投诉 评论

只要变成工作狂,孤独就找不到你春节前就换了一间比从前那间更宽敞的房子。本意是逃离上一个糟糕的邻居,结果搬进了让自己感到空旷的空间。虽然实际上它也没多大:上周买的扩香刚打开摆在最角落的洗手间里,味道立刻在几秒……Spring里面的Import注解到底是个啥?Spring提供了几种方式来注册Bean,日常开发中使用最多的是ComponentScan。得益于ComponentScan,注册bean非常的简单,只需要在被注册的类上声明C……56岁温兆伦开400万跑车遭批,大街上兜风随意停车6月8日,演员温兆伦在社交平台上更新了一组照片,他在大街上开着价值上百万的豪车兜风,行为高调引发热议。56岁的温兆伦身穿绿色T恤,开着一辆十分惹眼的跑车。跑车外观呈淡紫色……姓名改名(怎么改名字)姓名改名(怎么改名字)姓名是父母的馈赠,很多人也许一生都不会改变自己的名字,但在成长的过程中,也许是因为父母离异再婚,或者是因为与外国人结婚,更或者是就想换个名字重新开始……乌鲁木齐兰乔圣菲(乌鲁木齐60个最偏僻小区)乌鲁木齐兰乔圣菲(乌鲁木齐60个最偏僻小区)乌鲁木齐这几年城市扩容非常厉害,东西北不断扩展,导致以前很多是山沟沟或荒漠地带,如今,变成了小区,甚至还在大力开发,比如,10……西安为什么多发地裂缝西安多发地裂缝的主要原因有两条:1、构造活动西安断陷一直处于下沉状态,长安临潼断裂也进行着南升北降的活动,西安11条地裂缝带均处于下降的北盘,其分布及活动均受长安临……十大婴儿奶粉(超人气奶粉选购清单)十大婴儿奶粉(超人气奶粉选购清单)给宝宝挑选奶粉时,因根据宝宝自身体体质为切入点,才能找到更适合自己宝宝的奶粉。通过对2019十大人气婴儿奶粉的特色和功效分析,总结出了宝……植树节口号(植树节口号简短植树节主题宣传句子)植树节口号(植树节口号简短植树节主题宣传句子)2021年植树节最新横幅标语3月12日植树节就要到了,在这一天我们要植树绿化,为地球出一份力!只是有关2021植树节的……诺楠文化创作团队陈仁波陈仁波资深音乐制作人、中国流行音乐家协会会员。毕业于星海音乐学院,曾获第三届孔雀奖全国高等艺术院校声乐大赛学生流行组金奖,2017年获得诺楠文化(深圳)有限公司举办的【亚……物理性污染的特点物理性污染是指由物理因素引起的环境污染,如:放射性辐射、电磁辐射、噪声、光污染等。物理性污染主要指食品被放射性物质污染。放射性物质源于宇宙射线和地壳中的放射性物质。核试验及和平……房屋常识没有房产可以分户吗有哪位能说说很多朋友们现在对于房产方面的知识了解的偏少,不管是从购房的角度,或者是装修房子的角度,我们都需要对房产方面的一些知识进行了解,所以小编今天就在网上搜集了一些房产方面相关的知识来……吊带裙怎么穿最时髦内搭吊带裙搭配流行单穿吊带裙是性感风,但是现在,内搭吊带裙才是潮流王道!内搭的穿法减龄又清新,性感的同时又可以遮肉!快跟小编来看内搭吊带裙的搭配流行LOOK吧!内搭吊带裙新穿法!吊带裙穿出……
发财树怎么养发财树养殖方法藏在书中的精彩realme是什么牌子(realme是什么)风水选址!(按风水选址的城市!)母爱留在心里销毁对方微信聊天记录(销毁对方微信聊天)思窝星图腾布里斯班现代艺术馆GOMA,艺术无标准有高下走一步再走一步作文字欲悲闻鬼叫(论被写尽的古典诗词)十二生肖为什么没有猫(十二生肖)蜗牛湖南蛇成龙真实事件老汉竟看见真实巨蛇渡劫成龙天天涂素颜霜好吗素颜霜可以天天用吗创业板股票是什么关于祝你幸福的唯美句子离婚协议书哪种家庭物品损坏保险公司能理赔保护地球环境的建议书这本奇书,祸害中国上千年,3分钟读懂,教你。。。美术教案不同的母爱波德莱尔诗歌月之愁原文及赏析今日全国黑仔猪价格国内猪肉价格今日价

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找