前言
后續(xù)的所有文章將開始圍繞上篇博客:spring 5.0.x源碼學(xué)習(xí)系列二: 從AnnotationConfigApplicationContext開始迄埃,進(jìn)入spring世界的運(yùn)行流程圖展開, 并根據(jù)實(shí)際的代碼來詳細(xì)解析题禀。接下來開始進(jìn)入正文
一、AnnotationConfigApplicationContext的無參構(gòu)造方法
上篇博客(上面有鏈接, 可以自行查看)中逆瑞,大致介紹了無參構(gòu)造方法的主要作用, 接下來將根據(jù)源碼詳細(xì)介紹.
1.1 項(xiàng)目demo
項(xiàng)目結(jié)構(gòu)非常簡單,大致結(jié)構(gòu)如下:
1.2 debug運(yùn)行項(xiàng)目
1. 進(jìn)入帶參AnnotationConfigApplicationContext構(gòu)造方法
2. 調(diào)用無參構(gòu)造方法, 但因?yàn)槔^承了GenericApplicationContext類, 所以要先執(zhí)行父類的無參構(gòu)造方法, 此時(shí)實(shí)例化了bean工廠
3. bean工廠初始化完畢
4. 實(shí)例化AnnotationBeanDefinitionReader
5. AnnotationBeanDefinitionReader自己維護(hù)了spring的上下文, 并開始準(zhǔn)備注冊(cè)spring的6個(gè)內(nèi)置bean
6. 重載方法
7. 從BeanDefinitionRegistry中獲取bean工廠
8. 注冊(cè)spring的六個(gè)內(nèi)置bean(這些bean的作用是后置處理器)
-
源碼注釋圖
-
判斷是否存在beanName
//AbstractApplicationContext.java @Override public boolean containsBeanDefinition(String beanName) { // getBeanFactory()獲取的是DefaultListableBeanFactory, // 所有會(huì)進(jìn)到DefaultListableBeanFactory的containsBeanDefinition // 方法中 return getBeanFactory().containsBeanDefinition(beanName); } // DefaultListableBeanFactory.java @Override public boolean containsBeanDefinition(String beanName) { Assert.notNull(beanName, "Bean name must not be null"); return this.beanDefinitionMap.containsKey(beanName); }
-
注冊(cè)spring內(nèi)置bean源碼
// 注冊(cè)spring內(nèi)置bean的源碼 private static BeanDefinitionHolder registerPostProcessor( BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) { definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); // 這行代碼很重要, 在spring中基本上所有的beanDefinition的注冊(cè) // 都要走BeanDefinitionRegistry的registerBeanDefinition方法。 // spring的單一原則做的真好(真香!) // 這里的register又是哪個(gè)對(duì)象呢亮垫? 同樣的它是AnnotationConfigApplicationContext // 但registerBeanDefinition方法的調(diào)用不在父類的父類, // 而是在父類GenericApplicationContext中 registry.registerBeanDefinition(beanName, definition); return new BeanDefinitionHolder(definition, beanName); }
9. 后面還有5個(gè)內(nèi)置bean需要注冊(cè), 注冊(cè)方式跟第八步大同小異羔沙,都是先判斷是否存在再創(chuàng)建RootBeanDefinition再注冊(cè)到bean工廠, 這里就不累述了
- 具體還剩哪5個(gè)內(nèi)置bean可以參考我的上一篇博客spring 5.0.x源碼學(xué)習(xí)系列二: 從AnnotationConfigApplicationContext開始躺涝,進(jìn)入spring世界的第一封流程圖, 或者看下面的源碼
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { // 此處是為了獲取bean工廠, 獲取bean工廠的目的很簡單, 就是為了注冊(cè)spring內(nèi)置的六個(gè)bean DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { // 不知道具體干啥的, 后面有機(jī)會(huì)再補(bǔ)充 if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } // 添加一個(gè)上下文注解自動(dòng)裝配的候選解析器(具體做啥的, 目前還沒研究到) if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } // 存儲(chǔ)BeanDefinitionHolder的set集合, 在注冊(cè)spring內(nèi)置bean這一過程中, 這個(gè)變量沒用, 雖然方法中return了, 但調(diào)用的地方并沒有接收它 Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); // 驗(yàn)證bean工廠中是否包含名字叫 "這么一長串的beanDefinition" - -! // 什么叫BeanDefinition呢? Java中描述一個(gè)類(比如常用的User類)是用 // 類型為Class的類來描述, 在spring中是用BeanDefinition來描述一個(gè)bean // 的。使用過spring的人就明白, 一個(gè)beans可以設(shè)置有許多屬性, 比如scope扼雏、lazy坚嗜、description、bean的class诗充、bean的name等等. // BeanDefinition就是用來存儲(chǔ)這些信息的, 在spring創(chuàng)建bean時(shí), 會(huì)拿到這個(gè)bean對(duì)應(yīng)的beanDefinition信息來創(chuàng)建它苍蔬。 // BeanDefinition的類型有許多種, 比如: 現(xiàn)在看到的RootBeanDefinition、AnnotatedBeanDefinition蝴蜓、ScannedGenericBeanDefinition等等, // 每個(gè)bean都有不同的作用, 比如ScannedGenericBeanDefinition類型的beanDefinition, // 咱們可以為這樣的beanDefinition手動(dòng)設(shè)置它的自動(dòng)裝配模式(Mybatis集成spring的源碼中利用了這一點(diǎn),后續(xù)有機(jī)會(huì)再記錄總結(jié))碟绑。 // 在往bean工廠注冊(cè)beanDefinition時(shí), 會(huì)往兩個(gè)數(shù)據(jù)結(jié)構(gòu)中存值, 一個(gè)是叫 // beanDefinitionMap另一個(gè)叫beanDefinitionNames。顧名思義, 分別是用來存儲(chǔ)beanDefinition(key為bean name)和bean name if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { // spring內(nèi)置bean的beanDefinition類型為RootBeanDefinition RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); // 傳入的為null, 所以先不管它 def.setSource(source); // 這行代碼做了兩件事, 一件是注冊(cè)bean, 另一件是添加到beanDefs, 雖然它的方法名叫注冊(cè)后置處理器, 但方法內(nèi)部還是注冊(cè)beanDefinition // 這里又用到了registry, 這個(gè)registry就是spring上下文 beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } 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)); } 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)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. 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)); } // Check for JPA support, and if present add the 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)); } 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)); } 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; }
10. spring內(nèi)置6個(gè)bean注冊(cè)完畢
11. this.scanner = new ClassPathBeanDefinitionScanner(this)
關(guān)于這行代碼, 它是初始化一個(gè)ClassPath的掃描器, 它的作用是掃描@ComponentScan注解中提供的掃描路徑, 但它并沒有起到這個(gè)作用, 因?yàn)檎嬲诮馕鯜ComponentScan注解時(shí), 是在內(nèi)部新new了一個(gè)ClassPathBeanDefinitionScanner對(duì)象
, 所以暫時(shí)沒發(fā)現(xiàn)它有啥用, 先跳過它, 以后若發(fā)現(xiàn)它有其他作用再來補(bǔ)上
二茎匠、小結(jié)
- AnnotationConfigApplicationContext類的無參構(gòu)造方法的主要作用就是:初始化bean工廠格仲、注冊(cè)spring的6個(gè)內(nèi)置bean
- 需要著重記住的幾個(gè)東西:
- spring的bean工廠類:
DefaultListableBeanFactory
- spring中最重要的內(nèi)置bean:
ConfigurationClassPostProcessor
, 它的作用在refresh
方法中會(huì)著重體現(xiàn)出來, 后續(xù)再總結(jié) - BeanDefinition的定義:
描述spring bean的數(shù)據(jù)結(jié)構(gòu)
- BeanDefinition的幾種類型:
RootBeanDefinition
、AnnotatedGenericBeanDefinition
诵冒、ScannedGenericBeanDefinition
凯肋、ConfigurationClassBeanDefinition(配置類中方法中擁有@Bean注解的類會(huì)被定義成這個(gè))
- spring上下文的幾種身份:
BeanDefinitionRegistry
和GenericApplicationContex
- spring源碼學(xué)習(xí)對(duì)應(yīng)GitHub 地址https://github.com/AvengerEug/spring/tree/develop/resourcecode-study
- I am a slow walker, but I never walk backwards.