最近工作之餘有時間和精力,加上平時對源碼比較感興趣,就開始啃起了Spring源碼。為加深印象寫了這篇博客,如有錯誤,望各位大佬不吝指正。 我看的是Spring5的源碼,從同性社區download下來後編譯,然後看源碼、寫註釋、一步一步debug,理論指導實踐,實踐再反作用於理論。 因為基於註解的開發 ...
最近工作之餘有時間和精力,加上平時對源碼比較感興趣,就開始啃起了Spring源碼。為加深印象寫了這篇博客,如有錯誤,望各位大佬不吝指正。
我看的是Spring5的源碼,從同性社區download下來後編譯,然後看源碼、寫註釋、一步一步debug,理論指導實踐,實踐再反作用於理論。
因為基於註解的開發是現在比較主流的開發模式,所以就從 AnnotationConfigApplicationContext 開始啃了。
因為代碼過多,執行流程過於複雜,就拆成了三篇來解析。
下麵就從這個類開始探究Spring上下文的初始化。
這裡需要留意 AnnotationConfigApplicationContext 繼承了 GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { private final DefaultListableBeanFactory beanFactory;
/** * 註意這個無參構造函數
*
* 這個初始化的DefaultListableBeanFactory就是Spring的Bean工廠 */ public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory(); } }
再來看看 AnnotationConfigApplicationContext 這個類
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { /** * 定義一個讀取註解的 BeanDefinition 讀取器 * 這個類在構造方法中被實例化 */ private final AnnotatedBeanDefinitionReader reader; /** * 定義一個掃描類路徑下加了註解的 BeanDefinition 掃描器 * 這個類在構造方法中被實例化 */ private final ClassPathBeanDefinitionScanner scanner; public AnnotationConfigApplicationContext() { // 實例化 BeanDefinition 讀取器 /** * 註冊所有註解相關的後置處理器 * 最重要的一個後置處理器 ConfigurationClassPostProcessor * BeanName 是 internalConfigurationAnnotationProcessor */ this.reader = new AnnotatedBeanDefinitionReader(this); // 實例化 BeanDefinition 掃描器 // 但是實際上掃描包的工作並不是 scanner 這個對象來完成的,是 Spring 自己創建的一個新的 ClassPathBeanDefinitionScanner // 這裡的 scanner 僅僅是為了程式員能夠在外部調用 AnnotationConfigApplicationContext 對象的 scanner 方法 this.scanner = new ClassPathBeanDefinitionScanner(this); } public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) { // 調用父類的構造方法,初始化 DefaultListableBeanFactory 的 Bean 工廠 super(beanFactory); // 實例化該讀取器 this.reader = new AnnotatedBeanDefinitionReader(this); // 實例化該掃描器 this.scanner = new ClassPathBeanDefinitionScanner(this); } /** * 這個構造方法需要傳入一個 @Configuration 註解配置類 * 通過註解讀取器讀取並解析 */ public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { /** * 由於繼承了父類,這裡會先去調用父類的構造方法,然後調用自身的構造方法 * * this.beanFactory = new DefaultListableBeanFactory(); * * 其實就是初始化一個 DefaultListableBeanFactory */ this(); /** * 將傳入的 @Configuration 配置類轉換為 BeanDefinition * 並添加到 DefaultListableBeanFactory 工廠的 BeanDefinitionMap 中 */ register(annotatedClasses); /** * 1、準備刷新山下文 * 2、通知子類刷新內部的 bean 工廠,得到創建的 DefaultListableBeanFactory 工廠 * 3、配置工廠的標準上下文特征 * 4、允許在上下文子類中對 bean 工廠進行後置處理 * 5、在上下文中調用工廠處理器方法,註冊為 bean * 6、註冊 BeanPostProcessor * 7、初始化此上下文的消息源 * 8、初始化應用事件廣播器【SpringBoot 的啟動源碼中與該方法有很大關係】 * 9、在特定的上下文子類中初始化其他特殊 bean * 10、檢查監聽器 bean 並註冊它們 * 11、實例化所有剩餘(非延遲初始化)單例 * 12、發佈相應的事件 */ refresh(); } public AnnotationConfigApplicationContext(String... basePackages) { /** * 由於繼承了父類,這裡會先去調用父類的構造方法,然後調用自身的構造方法 * * this.beanFactory = new DefaultListableBeanFactory(); * * 其實就是初始化一個 DefaultListableBeanFactory */ this(); scan(basePackages); refresh(); } }
這裡還要註意一下AnnotatedBeanDefinitionReader的實例化,代碼跟進去發現調用了 AnnotationConfigUtils 的 registerAnnotationConfigProcessors 方法,Spring在初始化上下文時,在Bean工廠中添加了很多輔助其初始化的類
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { // 獲取 Bean 工廠 DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { // AnnotationAwareOrderComparator 主要能解析 @Order 註解和 @Priority 註解 beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { // ContextAnnotationAutowireCandidateResolver 提供處理延遲載入的功能 beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } /** * 存放所有輔助類的信息 */ Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8); /** * BeanDefinition 的註冊,很重要,需要理解註冊的每個 Bean 的類型和作用 * * Spring 在初始化 ApplicationContext 和 Bean 工廠時,在 Bean 工廠中添加了很多輔助初始化 Bean 工廠的類 * * 1.ConfigurationClassPostProcessor 類型是 BeanFactoryPostProcessor * 2.AutowiredAnnotationBeanPostProcessor 類型是 BeanPostProcessor * 3.CommonAnnotationBeanPostProcessor 類型是 BeanPostProcessor * 4.PersistenceAnnotationBeanPostProcessor 類型是 BeanPostProcessor * 5.EventListenerMethodProcessor 類型是 BeanFactoryPostProcessor * 6.DefaultEventListenerFactory 類型是 EventListenerFactory */ /** * BeanName 是否包含 org.springframework.context.annotation.internalConfigurationAnnotationProcessor * BeanClass 是 ConfigurationClassPostProcessor,類型是 BeanFactoryPostProcessor */ 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)); } /** * BeanName 是否包含 org.springframework.context.annotation.internalAutowiredAnnotationProcessor * BeanClass 是 AutowiredAnnotationBeanPostProcessor,類型是 BeanPostProcessor */ 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)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. /** * BeanName 是否包含 org.springframework.context.annotation.internalCommonAnnotationProcessor * BeanClass 是 CommonAnnotationBeanPostProcessor,類型是 BeanPostProcessor */ 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. /** * 檢查 JPA 支持,如果存在,則添加 PersistenceAnnotationBeanPostProcessor * * BeanName 是否包含 org.springframework.context.annotation.internalPersistenceAnnotationProcessor * BeanClass 是 PersistenceAnnotationBeanPostProcessor,類型是 BeanPostProcessor */ 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)); } /** * BeanName 是否包含 org.springframework.context.event.internalEventListenerProcessor * BeanClass 是 EventListenerMethodProcessor,類型是 BeanFactoryPostProcessor */ 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)); } /** * BeanName 是否包含 org.springframework.context.event.internalEventListenerFactory * BeanClass 是 DefaultEventListenerFactory,類型是 EventListenerFactory */ 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; }
這個方法執行完後,可以看到 DefaultListableBeanFactory 中的 beanDefinitionMap 中已經有數據了,如果支持 JPA 則有6個元素,沒有則有5個。分別是 ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory,支持 JPA 的是 PersistenceAnnotationBeanPostProcessor。
這裡實例化的 ClassPathBeanDefinitionScanner 僅僅是為了讓程式員能夠在外部調用 AnnotationConfigApplicationContext 對象的 scanner 方法。Spring 在後面又重新初始化了一個 ClassPathBeanDefinitionScanner,用新的 ClassPathBeanDefinitionScanner 進行掃描。
回到一開始,我這裡是傳了一個@Configuration的配置類,所以從register方法往下跟,最後調用的是 AnnotatedBeanDefinitionReader 的 doRegisterBean 方法
/** * 將給定的 bean 類註冊為 bean,從類聲明的註釋中派生其元數據 */ private <T> void doRegisterBean(Class<T> annotatedClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers,
@Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) { // 根據指定的 bean 創建一個 AnnotatedGenericBeanDefinition AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); // 若這個類是需要跳過解析的類,則返回 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } // 指定創建 bean 實例的回調方法,此時為 null abd.setInstanceSupplier(supplier); // 解析類的作用域元數據 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); // 添加類的作用域元數據 abd.setScope(scopeMetadata.getScopeName()); /** * 生成 BeanName * 調用 AnnotationBeanNameGenerator.generateBeanName() */ String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); /** * 處理類當中的通用註解 * 主要處理 @Lazy @DependsOn @Primary @Role @Description 等註解 * 處理完成之後將值賦給到 AnnotatedGenericBeanDefinition 對應的屬性中 */ AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); /** * 如果在向容器註冊註解 BeanDefinition 時,使用了額外的限定符註解則解析 * byName 和 qualifiers 變數是 Annotation 類型的數組,裡面不僅存了 @Qualifier 註解 * 所以 Spring 遍歷這個數組判斷是否加了指定註解 * * 此時 qualifiers 為 null,if 語句不執行 */ if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary.class == qualifier) { // 設置 primary 屬性值 abd.setPrimary(true); } else if (Lazy.class == qualifier) { // 設置 lazyInit 屬性值 abd.setLazyInit(true); } else { /** * 如果使用了除 @Primary 和 @Lazy 以外的其他註解 * 則為該 Bean 添加一個根據名字自動裝配的限定符 */ // 向 Map<String, AutowireCandidateQualifier> qualifiers 集合中添加值 abd.addQualifier(new AutowireCandidateQualifier(qualifier)); } } } /** * 如果存在一個或多個用於自定義工廠的回調 * * 此時 customizers 為 null,if 語句不執行 */ if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); } } /** * 獲取 BeanDefinitionHolder 持有者容器 * 裡面包含的屬性值有 String beanName,BeanDefinition beanDefinition 和 String[] aliases 別名集合 */ BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); /** * 解析代理模型 */ definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); /** * 將最終獲取到的 BeanDefinitionHolder 持有者容器中包含的信息註冊給 BeanDefinitionRegistry * * AnnotationConfigApplicationContext 在初始化的時候通過調用父類的構造方法,實例化了一個 DefaultListableBeanFactory * 這一步就是把 BeanDefinitionHolder 這個數據結構中包含的信息註冊到 DefaultListableBeanFactory 中 * * DefaultListableBeanFactory 實現了 BeanDefinitionRegistry * * 此時傳入的 @Configuration 配置類已經註冊到 DefaultListableBeanFactory 工廠中 */ BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); }
這裡比較重要的是最後一行代碼,進行註冊操作,代碼如下:
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. // 用類的主要名稱註冊 BeanDefinition String beanName = definitionHolder.getBeanName(); /** * 將 beanName 註冊到 DefaultListableBeanFactory 工廠中 */ registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. // 如果有別名則為 BeanName 註冊別名 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { /** * 註冊別名 */ registry.registerAlias(beanName, alias); } } }
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } // 先從 Map<String, BeanDefinition> beanDefinitionMap 中獲取一次 BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); // 已註冊過則進行邏輯校驗 if (existingDefinition != null) { // 是否允許 BeanDefinition 覆蓋 if (!isAllowBeanDefinitionOverriding()) { // 不允許則拋異常 throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } // 已存在的角色是否小於傳入的 beanDefinition 角色 else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 如果傳入的 beanDefinition 和已存在的不相等 else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } // 重新存入 Map<String, BeanDefinition> beanDefinitionMap 中 this.beanDefinitionMap.put(beanName, beanDefinition); } // 不存在 else { // 是否已經啟動 bean 創建 if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { // 註冊到 Map<String, BeanDefinition> beanDefinitionMap 集合中 this.beanDefinitionMap.put(beanName, beanDefinition); // 用新的 beanDefinitionNames 替換舊的 List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; // 從集合中移除該 bean 名稱 removeManualSingletonName(beanName); } } // 還未啟動 bean 創建,即仍在啟動註冊階段 else { // 註冊到 Map<String, BeanDefinition> beanDefinitionMap 集合中 this.beanDefinitionMap.put(beanName, beanDefinition); // 添加 bean 名稱到 beanDefinitionNames 數據集合中 this.beanDefinitionNames.add(beanName); // 從集合中移除該 bean 名稱 removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
register 方法執行完成,此時傳入的 @Configuration 配置類已經註冊到 DefaultListableBeanFactory 工廠中
那這一篇就先到這裡,有問題或者錯誤歡迎大家溝通交流
下一篇從 refresh 方法開始往下跟代碼