安庆大理运城常德铜陵江西
投稿投诉
江西南阳
嘉兴昆明
铜陵滨州
广东西昌
常德梅州
兰州阳江
运城金华
广西萍乡
大理重庆
诸暨泉州
安庆南充
武汉辽宁

Spring中的Configuration注解你真的了解吗?

10月6日 火凤派投稿
  环境:Springboot2。3。12。RELEASE
  关于使用Configuration注解后为何类内部使用Bean注解方法声明的方法在多次调用后会是返回相同的实例?1示例
  如下:ConfigurationpublicclassBeanConfig{BeanpublicDatedate(){CustomerDAOc1customer();CustomerDAOc2customer();System。out。println(c1c1);System。out。println(c2c2);returnnewDate();}BeanpublicCustomerDAOcustomer(){returnnewCustomerDAO();}}
  输出:c1com。pack。config。CustomerDAO1c0cf193c2com。pack。config。CustomerDAO1c0cf193
  将上面的Configuration注解换成Component后再次运行:c1com。pack。config。CustomerDAO7b7e4b20c2com。pack。config。CustomerDAO5ac0bf84
  多个实例。2原理
  使用Configuration注解的类会为何会保证多次方法的调用返回的是同一个实例?2。1创建Spring上下文
  创建上下文最核心的就是注册了一个BeanFactory处理器publicclassSpringApplication{publicConfigurableApplicationContextrun(String。。。args){ConfigurableApplicationCcontextcreateApplicationContext();}protectedConfigurableApplicationContextcreateApplicationContext(){returnthis。applicationContextFactory。create(this。webApplicationType);}}
  跟踪createApplicationContext方法publicclassSpringApplication{protectedConfigurableApplicationContextcreateApplicationContext(){returnthis。applicationContextFactory。create(this。webApplicationType);}}
  进入ApplicationContextFactorypublicinterfaceApplicationContextFactory{ApplicationContextFactoryDEFAULT(webApplicationType){try{switch(webApplicationType){caseSERVLET:当前是基于SERVLET容器的,所以创建下面这个实例returnnewAnnotationConfigServletWebServerApplicationContext();caseREACTIVE:returnnewAnnotationConfigReactiveWebServerApplicationContext();default:returnnewAnnotationConfigApplicationContext();}}};}
  进入AnnotationConfigServletWebServerApplicationContextpublicclassAnnotationConfigServletWebServerApplicationContextextendsServletWebServerApplicationContextimplementsAnnotationConfigRegistry{publicAnnotationConfigServletWebServerApplicationContext(){this。readernewAnnotatedBeanDefinitionReader(this);this。scannernewClassPathBeanDefinitionScanner(this);}}
  进入AnnotatedBeanDefinitionReader构造方法publicclassAnnotatedBeanDefinitionReader{publicAnnotatedBeanDefinitionReader(BeanDefinitionRegistryregistry){this(registry,getOrCreateEnvironment(registry));}publicAnnotatedBeanDefinitionReader(BeanDefinitionRegistryregistry,Environmentenvironment){this。this。conditionEvaluatornewConditionEvaluator(registry,environment,null);核心方法,这里非常重要,会注册系统的一些处理器AnnotationConfigUtils。registerAnnotationConfigProcessors(this。registry);}}
  进入AnnotationConfigUtilsregisterAnnotationConfigProcessors方法publicabstractclassAnnotationConfigUtils{publicstaticvoidregisterAnnotationConfigProcessors(BeanDefinitionRegistryregistry){registerAnnotationConfigProcessors(registry,null);}}
  进入AnnotationConfiguUtilsregisterAnnotationConfigProcessors方法publicclassAnnotationBeanDefinitionReader{publicstaticfinalStringCONFIGURATIONANNOTATIONPROCESSORBEANNAMEorg。springframework。context。annotation。internalConfigurationAnnotationPpublicstaticSetBeanDefinitionHolderregisterAnnotationConfigProcessors(BeanDefinitionRegistryregistry,NullableObjectsource){。。。判断当前上下文中是否有internalConfigurationAnnotationProcessor没有则注册专门用来处理Configuration注解的ConfigurationClassPostProcessor处理器if(!registry。containsBeanDefinition(CONFIGURATIONANNOTATIONPROCESSORBEANNAME)){RootBeanDefinitiondefnewRootBeanDefinition(ConfigurationClassPostProcessor。class);def。setSource(source);beanDefs。add(registerPostProcessor(registry,def,CONFIGURATIONANNOTATIONPROCESSORBEANNAME));}。。。returnbeanD}}
  以上在创建Spring上下文对象的时候注册了一个非常核心的处理器ConfigurationClassPostProcessor该类会处理带有Configuration注解的类。2。2执行处理器
  这里就会执行上一步中注册的BeanFactoryPostProcessor。
  上面注册的ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口publicclassSpringApplication{publicConfigurableApplicationContextrun(String。。。args){ConfigurableApplicationCcontextcreateApplicationContext();刷新上下文refreshContext(context);}}
  跟踪refreshContext方法,进入到如下代码执行publicabstractclassAbstractApplicationContextextendsDefaultResourceLoaderimplementsConfigurableApplicationContext{publicvoidrefresh()throwsBeansException,IllegalStateException{synchronized(this。startupShutdownMonitor){。。。执行BeanFactoryPostProcessor中的回调方法invokeBeanFactoryPostProcessors(beanFactory);。。。}}}
  进入invokeBeanFactoryPostProcessors方法publicabstractclassAbstractApplicationContextextendsDefaultResourceLoaderimplementsConfigurableApplicationContext{protectedvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactorybeanFactory){PostProcessorRegistrationDelegate。invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors());}}
  进入invokeBeanfactoryPostProcessors方法
  注意ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor也实现了BeanFactoryPostProcessor接口,这里方法的执行是会先执行BeanDefinitionRegistryPostProcessor的回调方法,最后再执行BeanFactoryPostProcessor中的回调方法。
  执行流程为:ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry该方法主要左右通过方法名称也能猜到处理并注册当前CLASSPATH下的所有类中符合条件的Bean。ConfigurationClassPostProcessorpostProcessBeanFactory该方法的作用finalclassPostProcessorRegistrationDelegate{publicstaticvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactorybeanFactory,ListBeanFactoryPostProcessorbeanFactoryPostProcessors){。。。Now,invokethepostProcessBeanFactorycallbackofallprocessorshandledsofar。执行ConfigurationClassPostProcessorpostProcessBeanFactory方法invokeBeanFactoryPostProcessors(registryProcessors,beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors,beanFactory);}privatestaticvoidinvokeBeanFactoryPostProcessors(C?extendsBeanFactoryPostProcessorpostProcessors,ConfigurableListableBeanFactorybeanFactory){执行ConfigurationClassPostProcessor中的回调for(BeanFactoryPostProcessorpostProcessor:postProcessors){postProcessor。postProcessBeanFactory(beanFactory);}}}
  进入ConfigurationClassPostProcessorpostProcessBeanFactory方法publicclassConfigurationClassPostProcessorimplementsBeanDefinitionRegistryPostProcessor,PriorityOrdered,ResourceLoaderAware,ApplicationStartupAware,BeanClassLoaderAware,EnvironmentAware{publicvoidpostProcessBeanFactory(ConfigurableListableBeanFactorybeanFactory){增强配置类enhanceConfigurationClasses(beanFactory);beanFactory。addBeanPostProcessor(newImportAwareBeanPostProcessor(beanFactory));}}2。3增强配置类
  接着上面进入enhanceConfigurationClasses方法publicclassConfigurationClassPostProcessor{publicvoidenhanceConfigurationClasses(ConfigurableListableBeanFactorybeanFactory){MapString,AbstractBeanDefinitionconfigBeanDefsnewLinkedHashMap();遍历当前上下文中注册的所有BeanDefinition集合,找到所有的配置类这里会就会找到两个,一个是启动类,一个是上面示例中的配置类BeanConfigfor(StringbeanName:beanFactory。getBeanDefinitionNames()){BeanDefinitionbeanDefbeanFactory。getBeanDefinition(beanName);。。。configBeanDefs。put(beanName,(AbstractBeanDefinition)beanDef);}if(configBeanDefs。isEmpty()NativeDetector。inNativeImage()){nothingtoenhancereturnimmediatelyenhanceConfigClasses。end();}ConfigurationClassEnhancerenhancernewConfigurationClassEnhancer();遍历找到所有的Configuration配置类for(Map。EntryString,AbstractBeanDefinitionentry:configBeanDefs。entrySet()){AbstractBeanDefinitionbeanDefentry。getValue();IfaConfigurationclassgetsproxied,alwaysproxythetargetclassbeanDef。setAttribute(AutoProxyUtils。PRESERVETARGETCLASSATTRIBUTE,Boolean。TRUE);SetenhancedsubclassoftheuserspecifiedbeanclassC?configClassbeanDef。getBeanClass();这里就将BeanConfig配置类进行创建代理C?enhancedClassenhancer。enhance(configClass,this。beanClassLoader);if(configClass!enhancedClass){beanDef。setBeanClass(enhancedClass);}}}}
  进入ConfigurationClassEnhancerenhance方法classConfigurationClassEnhancer{Thecallbackstouse。Notethatthesecallbacksmustbestateless。privatestaticfinalCallback〔〕CALLBACKSnewCallback〔〕{newBeanMethodInterceptor(),newBeanFactoryAwareMethodInterceptor(),NoOp。INSTANCE};privatestaticfinalConditionalCallbackFilterCALLBACKFILTERnewConditionalCallbackFilter(CALLBACKS);publicC?enhance(C?configClass,NullableClassLoaderclassLoader){if(EnhancedConfiguration。class。isAssignableFrom(configClass)){returnconfigC}创建代理类C?enhancedClasscreateClass(newEnhancer(configClass,classLoader));returnenhancedC}privateEnhancernewEnhancer(C?configSuperClass,NullableClassLoaderclassLoader){EnhancerenhancernewEnhancer();enhancer。setSuperclass(configSuperClass);enhancer。setInterfaces(newC?〔〕{EnhancedConfiguration。class});enhancer。setUseFactory(false);enhancer。setNamingPolicy(SpringNamingPolicy。INSTANCE);enhancer。setStrategy(newBeanFactoryAwareGeneratorStrategy(classLoader));这里就是设置代理类执行的方法拦截器最核心的就是上面的BeanMethodInterceptor类enhancer。setCallbackFilter(CALLBACKFILTER);enhancer。setCallbackTypes(CALLBACKFILTER。getCallbackTypes());}}
  进入BeanMethodInterceptor类privatestaticclassBeanMethodInterceptorimplementsMethodInterceptor,ConditionalCallback{publicObjectintercept(ObjectenhancedConfigInstance,MethodbeanMethod,Object〔〕beanMethodArgs,MethodProxycglibMethodProxy)throwsThrowable{。。。该方法中就是从Spring容器中获取当前的BeanreturnresolveBeanReference(beanMethod,beanMethodArgs,beanFactory,beanName);}}
  进入resolveBeanReference方法classConfigurationClassEnhancer{privateObjectresolveBeanReference(MethodbeanMethod,Object〔〕beanMethodArgs,ConfigurableBeanFactorybeanFactory,StringbeanName){ObjectbeanInstance(useArgs?beanFactory。getBean(beanName,beanMethodArgs):beanFactory。getBean(beanName));returnbeanI}}
  完毕!!!
  求个关注转发
  Spring自定义Advisor以编程的方式实现AOP
  SpringBootWebFlux整合SpringSecurity进行权限认证
  SpringbootSecurity基础应用(1)
  Springboot中Redis事务的使用及Lua脚本
  SpringCloudFeign实现原理源分析
  SpringCloud全链路追踪SkyWalking及整合Elasticsearch
  SpringCloud微服务日志收集管理ElasticStack完整详细版
  SpringCloud链路追踪zipkin及整合Elasticsearch存储
  SpringCloudGateway应用详解2内置过滤器
  Spring通过源码分析了解这3种Bean处理器的执行过程
  SpringBoot集群环境下使用Redis实现Session共享
投诉 评论 转载

拉风!NBA超巨开黑色法拉利,娶极品舞女,15年赚25亿养1当地时间10月9日,美国媒体拍到NBA球星保罗乔治与妻子丹妮埃拉开车外出与好友共享晚餐,只见,保罗乔治驾驶着一辆颇为少见的黑色款法拉利,停放在洛杉矶的闹市街头,非常吸睛。……蒙牛再次增持妙可蓝多背后乳企主业增长慢,奶酪成突破口?蒙牛将增持妙可蓝多,让奶酪这个新兴乳制品市场又掀起波澜。近日,蒙牛拟以30。92元股的价格,合计约7。98亿元收购妙可蓝多约2580万股,占后者股份总数5,若交易完成,蒙……喝咖啡不但不伤身,还防癌?专家表示这4类人,尽量远离咖啡导语:随着生活水平的不断提高,大部分年轻人由于工作压力较大,经常有着饮用咖啡的习惯,在早上起床之后喝一杯咖啡,不仅可以提神醒脑,还有助于提高工作效率,更快完成工作。爱乐养生指南……一直到月底,承德这个景区免门票啦免门票!一直到月底!承德这个景区免门票!你没听错,据了解承德兴隆山景区在9月30日之前免门票!(因为他们周年庆)这波羊毛咱得薅!9月这波福利赶紧收藏吧!……自然食养五谷为养,健康生活要遵循自然节奏中国的食养文化历史十分悠久,具体可以追溯至古代时期。尽管物转星移,时代变迁,可食疗、食养、食补的养生观念仍然在不断传承,留存于每代人的心中。饮食作为生活中的必需项,非常关……Spring中的Configuration注解你真的了解吗?环境:Springboot2。3。12。RELEASE关于使用Configuration注解后为何类内部使用Bean注解方法声明的方法在多次调用后会是返回相同的实例?1示……今年早春就流行复古牛仔裙,优雅干练又有个性,谁穿都美随着气温回升,相信不少小仙女已经开始准备春装了!不瞒大家说,我的早春氛围感单品已经在衣橱里躺了好几天了,今天终于可以借着这个机会分享给大家了,如果你正在为挑选单品而发愁,可以接……爆大冷!76人不敌重建球队,塔克怒吼全队,里弗应该下课NBA常规赛继续进行,76人对阵重建球队马刺,无论是阵容实力,还是比赛经验,主场作战的76人都具有明量的优势,这正是球队积攒胜绩的好机会,也是思比德和哈登重新树立自信心的时候,……中国vs美国工业实力有人说中国的工业实力是制造业大国不是制造业强国,我想光说是没用用数据说话用事实说用十个领域具工业实力代表性各打分满分是10分,1半导体设备美国是9分中国是4分,毕竟是美国的半导……家庭要不要买些黄金买多少黄金的价值和价格走向,众说纷纭,买黄金能发财吗?不可能!买黄金能亏本吗?也不可能!买黄金能保值增值吗?一定程度!买黄金能避险吗?一定!一些经济学家和大牛们,经常在网上发布观点,……谢贵湘主持召开张管局十一旅游接待及旅游安全工作部署会会议现场红网时刻张家界9月29日讯(武陵源区融媒体中心通讯员曹译文)9月28日,武陵源区委副书记,张管局党委副书记、常务副局长谢贵湘主持召开张管局十一旅游接待及旅游安全工……中国科学家研制新材料有望助力双碳和太空探测白天可比环境温度高170摄氏度,夜晚可比环境温度低20摄氏度,无需外部能源消耗近期,中国科学技术大学教授裴刚、研究员邹崇文等人研制出一种分别以太阳、太空为热源、冷源的冷热双吸材……
当敦煌文化邂逅现代时尚余生渐短,善待自己欢乐颂3利用李其行报仇的露西,她有多可怕就有多委屈从一房难求到一客难求,郑州房东甚至摆摊求租城市租房大调查威金斯何去何从全美超模大赛被骂翻!恶意剪辑引导网暴,虐待选手致生命危险阿凡达潘多拉边境发售再次延期,漫威蜘蛛侠开启预购泰国开放,客流翻倍,曼谷国际机场将被泼水节激增游客挤爆夏天穿黑色如何避免重在参与?场合选对,美貌翻倍到手价429元,这款诺基亚2660Flip翻盖手机老人必备46岁的丘索维金娜又夺冠了A股机器人迎来超级风口!未来或将前程似锦的7家机器人企业捉蚊趣事(新华全媒)我们的田野最美秋色是丰收描绘金色梦想畅想童年时光书信600字轮滑鞋能不能洗轮滑鞋能洗吗生命最后的微光他是黑洞中最帅反派小弟,19年过去,现状令人唏嘘塑胶跑道的施工要求和点位线要求小绵羊张艺兴的进化论心理中年的危机,女人四十岁以后容易出轨的机率最高男人在床上哪些行为会让女人讨厌立冬之后吃什么更好?孕妇夏季室内空气湿度多少为宜

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找七猫云易事利