环境: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共享