日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring5源码 - 03 普通对象对应的BeanDefinition是如何存入DefaultListableBeanFactory#beanDefinitionMap 源码分析

發(fā)布時(shí)間:2025/3/21 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring5源码 - 03 普通对象对应的BeanDefinition是如何存入DefaultListableBeanFactory#beanDefinitionMap 源码分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • Pre
  • Spring處理bdmap 的理念
  • 源碼分析
    • Step1 : `this();` 【初始化BeanFactory】
    • register(componentClasses); 【注冊(cè)bean】
    • refresh();


Pre

接上文 Spring5源碼 - 02 Bean和Java對(duì)象的區(qū)別與猜想驗(yàn)證BeanDefinition

我們分析了流程, 也從理論上描述了 普通對(duì)象 ----- BeanDefinition ------Bean對(duì)象之間的關(guān)聯(lián),提到了一個(gè)BeanDefinition的Map集合 (我們稱之為 bdmap ,后面都用這個(gè)簡(jiǎn)稱代替 ),

那從源碼里面怎么體現(xiàn)出來bdmap 的呢?

本篇博文將帶你一一掀開


Spring處理bdmap 的理念

因?yàn)檫@個(gè)bdmap 對(duì)應(yīng)Spring太重要了,不僅要處理用戶配置的掃描包下的bean,還有一點(diǎn)更重要Spring內(nèi)置的bean 也需要依靠這個(gè)bdmap .
如果這個(gè)bdmap 完全交給開發(fā)者來處理,比如你把這個(gè)map中的數(shù)據(jù)給remove掉了,等等之類的不可信任的操作,結(jié)果可想而知,所以Spring封裝了一些API,僅允許開發(fā)者通過Spring提供的API來修改bdmap .


源碼分析

那我們來看下Spring是如何來封裝的這個(gè)API呢?

接上文中的 BeanFactoryPostProcessor Bean工廠后置處理器

ConfigurableListableBeanFactory 這個(gè) beanFactory對(duì)象 是Spring封裝的用于提供給開發(fā)者修改BeanDefinition的一個(gè)接口類。

提供了 getBeanDefinition 方法

beanFactory.getBeanDefinition("artisan1");

ctrl + alt + b 打開實(shí)現(xiàn)類 DefaultListableBeanFactory

我們來看下 定義 beanDefinitionMap

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

Spring也是用的Map來存儲(chǔ)的 ~


那我要看 spring是如何把BeanDefinition放到這個(gè) beanDefinitionMap 中的,那我就需要重點(diǎn)觀察 beanDefinitionMap 這個(gè)對(duì)象,Spring是在什么時(shí)候賦值的 .

我們知道了 DefaultListableBeanFactory 有個(gè)屬性 是 beanDefinitionMap

先找DefaultListableBeanFactory

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

看下AnnotationConfigApplicationContetxt的類關(guān)系

跟進(jìn)去構(gòu)造函數(shù)

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {this();register(componentClasses);refresh();}
  • this() : 調(diào)用無參構(gòu)造函數(shù),會(huì)先調(diào)用父類GenericApplicationContext的構(gòu)造函數(shù) ,父類的構(gòu)造函數(shù)里面就是初始化DefaultListableBeanFactory,并且賦值給beanFactory . 本類的構(gòu)造函數(shù)里面,初始化了一個(gè)讀取器:AnnotatedBeanDefinitionReader read,一個(gè)掃描器ClassPathBeanDefinitionScanner scanner . scanner的用處不是很大,它僅僅是在我們外部手動(dòng)調(diào)用 .scan 等方法才有用,常規(guī)方式是不會(huì)用到scanner對(duì)象的 .

  • register(componentClasses): 注冊(cè)配置類 即 AppConfig.class

  • refresh() : 容器刷新,這個(gè)是最核心的方法。 很重要


回到this(),我們來看下源碼

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {}

父類的構(gòu)造函數(shù)

實(shí)例化DefaultListableBeanFactory

DefaultListableBeanFactory非常最重要, 主要就是用來生產(chǎn)和獲得Bean的


接著子類的構(gòu)造函數(shù)

this.reader = new AnnotatedBeanDefinitionReader(this); 初始化一個(gè)Bean讀取器

this.scanner = new ClassPathBeanDefinitionScanner(this);初始化一個(gè)掃描器,它僅僅是在我們外部手動(dòng)調(diào)用 .scan 等方法才有用,常規(guī)方式是不會(huì)用到scanner對(duì)象的


繼續(xù)看 new AnnotatedBeanDefinitionReader(this) 實(shí)例化建BeanDefinition讀取器

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {//注冊(cè)了實(shí)現(xiàn)Order接口的排序器beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}//設(shè)置@AutoWired的候選的解析器if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);/*** 為我們?nèi)萜髦凶?cè)了解析我們配置類的后置處理器ConfigurationClassPostProcessor* 名字叫:org.springframework.context.annotation.internalConfigurationAnnotationProcessor*/if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 為我們?nèi)萜髦凶?cè)了處理@Autowired 注解的處理器AutowiredAnnotationBeanPostProcessor* 名字叫:org.springframework.context.annotation.internalAutowiredAnnotationProcessor*/if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 為我們?nèi)萜髦凶?cè)處理@Required屬性的注解處理器RequiredAnnotationBeanPostProcessor* 名字叫:org.springframework.context.annotation.internalRequiredAnnotationProcessor*/if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 為我們?nèi)萜髯?cè)處理JSR規(guī)范的注解處理器CommonAnnotationBeanPostProcessor* org.springframework.context.annotation.internalCommonAnnotationProcessor*/if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 處理jpa注解的處理器org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor*/if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);}def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 處理監(jiān)聽方法的注解解析器EventListenerMethodProcessor*/if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}/*** 注冊(cè)事件監(jiān)聽器工廠*/if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}

主要工作

  • 注冊(cè)內(nèi)置BeanPostProcessor 開天辟地的元?jiǎng)譈ean
  • 注冊(cè)相關(guān)的BeanDefinition

  • Step1 : this(); 【初始化BeanFactory】

    沒有呢?我們知道實(shí)例化子類,父類也會(huì)被初始化,那往上找找吧

    可以看到是在父類GenericApplicationContext中初始化的DefaultListableBeanFactory

    這樣的話,我們把斷點(diǎn)打在下面一行 register(componentClasses)上,觀察this 中的對(duì)象 如下

    現(xiàn)在是有默認(rèn)的Spring初始化的時(shí)候自己的BeanDefinition , 沒有我們自己的bd ,那就繼續(xù)走,看看這個(gè)beanDefinitionMap什么時(shí)候會(huì)發(fā)生變化~


    register(componentClasses); 【注冊(cè)bean】

    先看結(jié)論

    說明這一步就完成了 從 普通對(duì)象 (注冊(cè)配置類)------- BeanDefinition ----------存入到 bdMap中的操作


    接下來分析下核心源碼

    流程如下

    如上 ,這個(gè)流程完成后, DefaultListableBeanFactory#beanDefinitionMap 就有了new AnnotationConfigApplicationContext(AppConfig.class)

    入?yún)⒅械?AppConfig.class 對(duì)應(yīng)的Bean了


    refresh();

    那這個(gè)AppConfig配置的掃描包下的bean,什么時(shí)候初始化呢? 那就是refresh這個(gè)方法了 ,下文繼續(xù)

    先看一眼,結(jié)論

    這個(gè)方法太重要了,一共有12個(gè)方法里面, 下篇博文 繼續(xù) 分析


    《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

    總結(jié)

    以上是生活随笔為你收集整理的Spring5源码 - 03 普通对象对应的BeanDefinition是如何存入DefaultListableBeanFactory#beanDefinitionMap 源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。