揭開AnnotationConfigApplicationContext類運(yùn)行的神秘面紗
一、運(yùn)行大致流程圖
在這里插入圖片描述
在這里插入圖片描述
二、解析
2.1 無參構(gòu)造方法
-
AnnotationConfigApplicationContext無參構(gòu)造方法
public AnnotationConfigApplicationContext() { // 在執(zhí)行此行代碼之前, 先執(zhí)行了父類的構(gòu)造方法 // 此段代碼做的事情: // 1. 初始化bean工廠 // 2. 初始化一個注解BeanDefinition讀取器 // 3. 將spring內(nèi)置的6個類封裝成RootBeanDefinition并注冊到bean工廠, // 具體是哪6個類可以查看上述的原理圖 this.reader = new AnnotatedBeanDefinitionReader(this); // 并沒啥用, 雖然ClassPathBeanDefinitionScanner // 類的作用是掃描@ComponentScan注解提供的包路徑。 // 但實(shí)際上它并沒有做掃描工作, spring內(nèi)部掃描路徑 // 的時候, 是在內(nèi)部新new了一個ClassPathBeanDefinitionScanner, // 這個屬性目前沒啥用, 當(dāng)然我們可以獲取這個對象 // 調(diào)用它的scan方法, 但是沒有必要! 因?yàn)? // @ComponentScan可以支持多個掃描路徑。 // 那這個類有什么用呢?跟剛剛的解釋一樣, // 我們可以自己new一個ClassPathBeanDefinitionScanner對象或者擴(kuò)展他, // 利用它的掃描功能(因?yàn)樗鞘褂肁SM來掃描的) // Mybatis源碼中就是自己擴(kuò)展了 // ClassPathBeanDefinitionScanner類 this.scanner = new ClassPathBeanDefinitionScanner(this); }- AnnotationConfigApplicationContext父類GenericApplicationContext無參構(gòu)造方法
public GenericApplicationContext() { // 實(shí)例化spring bean工廠: DefaultListableBeanFactory this.beanFactory = new DefaultListableBeanFactory(); }- 注冊spring內(nèi)置的6個bean至bean工廠代碼:org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { // 解析傳入的registry, 獲取bean工廠, // 根據(jù)調(diào)用鏈或debug可知, 它就是 // AnnotationConfigApplicationContext上下文, // 因?yàn)樗母割怗enericApplicationContext維護(hù)了一個bean工廠, // 并提供了get方法, 那么它自然也能擁有bean工廠 DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } // 無啥用, 雖然方法返回了它, 但調(diào)用處壓根沒接收這個返回值 Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); 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)); } 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; }
2.2 register方法
-
源碼
/** * 傳入的是一個被注解類的Class數(shù)組, 可以是配置類也可以是普通類 * (什么叫配置類什么叫普通類, 在后續(xù)的源碼系列中會更新) * @param annotatedClasses one or more annotated classes */ public void register(Class<?>... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); // 此處用到了構(gòu)造方法new出來的AnnotatedBeanDefinitionReader, // 這里解釋下, 為什么能用這個類來將傳入的類注冊到bean工廠中: 因?yàn)樗鼉?nèi) // 部維護(hù)了一個registry, 這個registry就是AnnotationConfigApplicationContext this.reader.register(annotatedClasses); } -
作用: 將傳入的被注解的類以AnnotatedGenericBeanDefinition的類型注冊到bean工廠。 至此, 還沒有一個bean被創(chuàng)建出來。以下為注冊AnnotatedGenericBeanDefinition的具體代碼邏輯, 可以看到注冊bean調(diào)用了這個方法:
registerBeanDefinition(這個方法很重要. 后續(xù)注冊beanDefinition到bean工廠基本上都會用到這個方法)
在這里插入圖片描述
2.3 refresh方法
這個方法可以說是spring的核心入口方法了, 在內(nèi)部做了太多太多的事情。
-
源碼(每行代碼執(zhí)行意義在注釋中有寫到, 先使用黑箱理論, 大致了解它是干啥的, 具體先解析到invokeBeanFactoryPostProcessors此方法, 后續(xù)的方法還沒往后讀, 以后補(bǔ)充):
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 這個方法執(zhí)行完成, spring的bean單例容器中會存在三個bean, // 分別是systemEnvironment, environment, systemProperties prepareBeanFactory(beanFactory); try { // 該方法沒有做任何事, 內(nèi)部無任何邏輯 postProcessBeanFactory(beanFactory); // 調(diào)用后置處理器, 此方法太重要了, 調(diào)用過程參考下圖 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } } -
invokeBeanFactoryPostProcessors方法運(yùn)行原理圖, 該方法大致包含: 調(diào)用手動添加的BeanFactoryPostProcessor后置處理器、調(diào)用spring內(nèi)置后置處理器ConfigrationClassPostProcessor, 主要解析配置類、給全注解類添加cglib代理等等這里先把它曬出來, 后續(xù)再詳細(xì)
在這里插入圖片描述
三、小結(jié)
- 上述為本次博客內(nèi)容
- github地址: https://github.com/AvengerEug
- I am a slow walker, but I never walk backwards.