javascript
Spring5源码 - 03 普通对象对应的BeanDefinition是如何存入DefaultListableBeanFactory#beanDefinitionMap 源码分析
文章目錄
- 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;}主要工作
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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring5源码 - 02 Bean和
- 下一篇: gradle idea java ssm