spring boot的BeanDefinitionMap初始化过程

1.执行在Initializer中congtext创建BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
2.获取BeanFactory中BeanDefinitionMap的(PriorityOrdered)BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
    处理ConfigurationClassPostProcessor
3.获取BeanFactory中BeanDefinitionMap的(Ordered)BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
4.获取BeanFactory中BeanDefinitionMap的BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
5.统一执行1-4步中的BeanDefinitionRegistryPostProcessor#postProcessBeanFactory
6.统一执行1-4步中的BeanFactoryPostProcessor#postProcessBeanFactory
7.步5和步6执行完可能继续生成剩余未处理的BeanFactoryPostProcessor此时统一按:PriorityOrdered=>Ordered=>普通调用#postProcessBeanFactory
    在PriorityOrdered中存在PropertySourcesPlaceholderConfigurer对于BeanDefinition中字符串${}进行替换
        visitParentName(beanDefinition);
        visitBeanClassName(beanDefinition);
        visitFactoryBeanName(beanDefinition);
        visitFactoryMethodName(beanDefinition);
        visitScope(beanDefinition);
        visitPropertyValues(beanDefinition.getPropertyValues());
        ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
        visitIndexedArgumentValues(cas.getIndexedArgumentValues());
        visitGenericArgumentValues(cas.getGenericArgumentValues());


ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry执行过程:
1.parse(Set<BeanDefinitionHolder> configCandidates):解析BeanDefinitionHolder
2.BeanDefinition包装为ConfigurationClass
3.processConfigurationClass(ConfigurationClass configClass):解析ConfigurationClass
4.doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
    1:processMemberClasses()解析内部类:存在Configuration则执行步骤3.processConfigurationClass(ConfigurationClass configClass)
    2:解析SourceClass可重复注解@PropertySource,获取value(为文件的位置),并添加ResourcePropertySource到Environment(instanceof ConfigurableEnvironment)
    3.解析SourceClass可重复注解@ComponentScan,通过ClassPathBeanDefinitionScanner扫描文件获取到ScannedGenericBeanDefinition并注册到Registry.BeanDefinitionMap,遍历scannedBeanDefinitions是否为Configuration候选者,是则包装为ConfigurationClass并执行则执行步骤3.processConfigurationClass(ConfigurationClass configClass)
    4.getImports(sourceClass)并解析:@Import中的value值(TODO:涉及到4种情况)
    5.解析注解@ImportResource然后configClass.addImportedResource(resolvedResource, readerClass);
    6.获取sourceClass中@bean方法并configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    7.获取sourceClass所有接口中的默认@bean方法并configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    8.获取sourceClass父类(除去java包下或者排除knownSuperclasses)如果存在则执行步骤4.doProcessConfigurationClass
5.处理延时processDeferredImportSelectors
    1.org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector这里面会对META-INF/spring.factories中的EnableAutoConfiguration.class进行配置
6.注册ConfigurationClasses到Registry.BeanDefinitionMap
    1.判断是否shouldSkip(注意Configuration有父子关系,也需要判断)
    2.ConfigurationClass如果是被父亲引入的需要将该注册到BeanDefinitionMap
    3.注册configClass.getBeanMethods(),注册到BeanDefinitionMap
    4.loadBeanDefinitionsFromImportedResources,这里会对资源文件进行判断读取".groovy":GroovyBeanDefinitionReader.class,其他的按XmlBeanDefinitionReader.class读取
    5.loadBeanDefinitionsFromRegistrars调用ImportBeanDefinitionRegistrar#registerBeanDefinitions
7.获取当前BeanDefinitionMap中未处理的Configuration进行执行步骤1parse(Set<BeanDefinitionHolder> configCandidates)

通过分析完bean definition如何加载到BeanFactory,我们提出几个问题:
1.@Conditional和@ConfigurationCondition的使用原理 以及两个周期(PARSE_CONFIGURATION,REGISTER_BEAN)
2.@Import的使用原理
Configuration ImportSelector ImportBeanDefinitionRegistrar (regular component)classes
3.如何进行自动配置,AutoConfigurationImportSelector原理
4.什么时候加载PropertySourcesPlaceholderConfigurer
5.@ComponentScan扫描
6.BeanDefinitionRegistryPostProcessor和BeanDefinitionPostProcessor区别

BeanDefinitionRegistryPostProcessor主要bean definition定义 包括BeanDefinitionPostProcessor的定义
BeanDefinitionPostProcessor        主要bean definition处理

7.ApplicationContextInitializer和ApplicationContext区别
8.SpringApplicationRunListeners的生命周期
9.AnnotationMetadata的实现类StandardAnnotationMetadata(基于AnnotatedElementUtils)和AnnotationMetadataReadingVisitor(基于asm实现) asm实现相对较弱只能识别当前类的字节码内容
10.PropertySourcesPropertyResolver的使用原理

        MutablePropertySources propertySources = new MutablePropertySources();
        Map<String,Object> map = new HashMap<>(16);
        map.put("application.name","Test");
        map.put("port","Test");
        map.put("application.port","${port:9080}");
        propertySources.addLast(new MapPropertySource("hello",map));
        PropertySourcesPropertyResolver propertySourcesPropertyResolver = new PropertySourcesPropertyResolver(propertySources);

        String s0 = propertySourcesPropertyResolver.getProperty("application.port");
        String s1 = propertySourcesPropertyResolver.resolvePlaceholders("${application.port}");
        String s2 = propertySourcesPropertyResolver.resolveRequiredPlaceholders("${application.port}");

spring对bean创建过程的扩展
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessPropertyValues
    RequiredAnnotationBeanPostProcessor
    AutowiredAnnotationBeanPostProcessor
invokeAwareMethods(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware)
org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
    ApplicationContextAwareProcessor#invokeAwareInterfaces(EnvironmentAware,ApplicationEventPublisherAware,ApplicationContextAware...)
    InitDestroyAnnotationBeanPostProcessor@PostConstruct
invokeInitMethods=((InitializingBean) bean).afterPropertiesSet();
invokeCustomInitMethod
org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization

对于bean实现SmartInitializingSingleton进行处理(如RestTemplate的LoadBalanced)
注意factorybean.getObject后会执行org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
DefaultListableBeanFactory#preInstantiateSingletons初始化单例bean后对SmartInitializingSingleton进行继续加工处理

容器关闭时候:
手动关闭org.springframework.context.support.AbstractApplicationContext#close
外部命令触发:org.springframework.context.ConfigurableApplicationContext#registerShutdownHook
扩展流程:
发布事件ContextClosedEvent
org.springframework.context.LifecycleProcessor#onClose
org.springframework.beans.factory.DisposableBean#destroy
org.springframework.context.support.AbstractApplicationContext#onClose

dependentBeanMap  key:beanName value:依赖beanName的bean
dependenciesForBeanMap key:beanName value:beanName依赖的bean
singletonObjects:
earlySingletonObjects:
singletonFactories:
registeredSingletons:
singletonsCurrentlyInCreation:
alreadyCreated:
mergedBeanDefinitions:
beanDefinitionMap:

org.springframework.beans.factory.support.AbstractBeanDefinition#autowireMode

AUTOWIRE_BY_NAME|AUTOWIRE_BY_TYPE会对bean中的PropertyDescriptor进行分析注入,而@autowire是通过后置处理postProcessPropertyValues进行处理添加到PropertyValues
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 229,362评论 6 537
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,013评论 3 423
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 177,346评论 0 382
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,421评论 1 316
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,146评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,534评论 1 325
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,585评论 3 444
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,767评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,318评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,074评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,258评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,828评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,486评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,916评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,156评论 1 290
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,993评论 3 395
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,234评论 2 375

推荐阅读更多精彩内容