java架構之路-(spring原始碼篇)springIOC容器原始碼解析(上)
我們這次來叭叭一下Spring的原始碼,這次部落格主要來說說Spring原始碼,先粗略的擼一遍,下篇部落格選幾個重點去說,由於過於複雜,我也是看了一點點,我們先來過一遍原始碼,然後上流程圖,最後我們再回頭總結一下,我們來循序漸進的叭叭一下。
我們來回顧一下上次Spring部落格的內容,每次都有用到AnnotationConfigApplicationContext來載入我們的配置類,我們就從這裡開始。
/** * Create a new AnnotationConfigApplicationContext, deriving bean definitions * from the given annotated classes and automatically refreshing the context. 建立新的註釋configapplicationcontext,獲得bean定義並自動重新整理上下文。 * @param annotatedClasses one or more annotated classes, 我們的配置類 * e.g. {@link Configuration @Configuration} classes */ public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }
翻譯過來就是“建立新的註釋configapplicationcontext,獲得bean定義並自動重新整理上下文”。三個方法,我們先來一個個看,優先看父類有沒有構造方法。AnnotationConfigApplicationContext繼承了GenericApplicationContext類,所以我們先看GenericApplicationContext類的構造方法。程式碼很簡單
父類構造方法
/** * Create a new GenericApplicationContext. * @see #registerBeanDefinition * @see #refresh */ public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }
這裡建立了一個新的DefaultListableBeanFactory物件,也是我們熟悉的beanFactory物件,記住是DefaultListableBeanFactory物件。我們回到AnnotationConfigApplicationContext的this方法。
this
/** * Create a new AnnotationConfigApplicationContext that needs to be populated * through {@link #register} calls and then manually {@linkplain #refresh refreshed}. */ public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this);//註解型別的解析器 this.scanner = new ClassPathBeanDefinitionScanner(this);//包掃描器 }
再往下扒一層。看一下那個AnnotatedBeanDefinitionReader註解型別的解析器是怎麼建立的,裡面都有什麼。
/** * Create a new {@code AnnotatedBeanDefinitionReader} for the given registry. * If the registry is {@link EnvironmentCapable}, e.g. is an {@code ApplicationContext}, * the {@link Environment} will be inherited, otherwise a new * {@link StandardEnvironment} will be created and used. * @param registry the {@code BeanFactory} to load bean definitions into, * in the form of a {@code BeanDefinitionRegistry} * @see #AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment) * @see #setEnvironment(Environment) */ public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) { this(registry, getOrCreateEnvironment(registry)); //優先設定了環境並存在快取內 }
設定了環境,將我們的beanFactory作為引數,做了this呼叫,
/** * Create a new {@code AnnotatedBeanDefinitionReader} for the given registry and using * the given {@link Environment}. 用registry和Environment建立一個新的AnnnotatedBeanDefinitionReader * @param registry the {@code BeanFactory} to load bean definitions into, * in the form of a {@code BeanDefinitionRegistry} * @param environment the {@code Environment} to use when evaluating bean definition * profiles. * @since 3.1 */ public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }
前三行不用看,第四行是用來解析我們@Conditional註解的。可以自己開啟瞧瞧原始碼。我們直接看第五行AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 也是很重要的程式碼,我們繼續叭叭。
/** * Register all relevant annotation post processors in the given registry. * @param registry the registry to operate on * @param source the configuration source element (already extracted) * that this registration was triggered from. May be {@code null}. * @return a Set of BeanDefinitionHolders, containing all bean definitions * that have actually been registered by this call */ public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { 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()); } } 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)); } // 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; }
原文的註釋為在給定的註冊器中處理所有有意義的後置處理器,基本就是是否包含***,如果包含就set進去。這段程式碼是用來初始化內部的元件的。走到這裡就已經初始化的Bean定義。也就是說我們的容器已經注入了定義資訊,還未例項化。
this方法的上半部分就說完了,我們再來看下半部分的new ClassPathBeanDefinitionScanner,建立一個類路徑掃描器,這個程式碼不多,就是判斷我們是否使用預設的類路徑掃描器。
1 /** 2 * Create a new {@code ClassPathBeanDefinitionScanner} for the given bean factory and 3 * using the given {@link Environment} when evaluating bean definition profile metadata. 4 * @param registry the {@code BeanFactory} to load bean definitions into, in the form 5 * of a {@code BeanDefinitionRegistry} 6 * @param useDefaultFilters whether to include the default filters for the 7 * {@link org.springframework.stereotype.Component @Component}, 8 * {@link org.springframework.stereotype.Repository @Repository}, 9 * {@link org.springframework.stereotype.Service @Service}, and 10 * {@link org.springframework.stereotype.Controller @Controller} stereotype annotations 11 * @param environment the Spring {@link Environment} to use when evaluating bean 12 * definition profile metadata 13 * @param resourceLoader the {@link ResourceLoader} to use 14 * @since 4.3.6 15 */ 16 public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, 17 Environment environment, @Nullable ResourceLoader resourceLoader) { 18 19 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); 20 this.registry = registry; 21 22 if (useDefaultFilters) { 23 registerDefaultFilters(); 24 } 25 setEnvironment(environment); 26 setResourceLoader(resourceLoader); 27 }
我們來直接看一下第23行程式碼,是否註冊一個預設的過濾器(掃描策略)。25行設定環境,26行設定資源載入器。
到這裡就已經制定好了我們的掃描策略了。
有點亂啊梳理一下。
register(annotatedClasses)
this部分就說你完了,再來看看register(annotatedClasses);字面意思來看是帶著我們的配置檔案註冊,我們來看一下程式碼。
/** * Register one or more annotated classes to be processed. * <p>Note that {@link #refresh()} must be called in order for the context * to fully process the new classes. * @param annotatedClasses one or more annotated classes, * e.g. {@link Configuration @Configuration} classes * @see #scan(String...) * @see #refresh() */ public void register(Class<?>... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); this.reader.register(annotatedClasses); }
用我們上一步的reader解析器去註冊,裡面是一個迴圈方法。最終呼叫doRegisterBean來真正的註冊。這一步我們先來簡單的叫做註冊吧。
直到這裡其實我們容器還是沒有建立的,這些都是一些前期的準備工作。最後也是最關鍵的一步才是我們的容器的例項化。refresh()方法。內容超多。
@Override 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. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. 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(); } } }
我們來逐個方法看一下都是做什麼的。
prepareRefresh()建立早期程式監聽器。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()通知子類重新整理Bean工廠
prepareBeanFactory(beanFactory)配置工廠上下文。
postProcessBeanFactory(beanFactory)處理Bean工廠的後置處理
invokeBeanFactoryPostProcessors例項化並呼叫所有註冊的Bean工廠的後置處理器
registerBeanPostProcessors(beanFactory)註冊Bean工廠的後置處理器
initMessageSource()初始化訊息源
initApplicationEventMulticaster()初始化事件多播器
onRefresh()初始化特殊定義的Bean
registerListeners()註冊事件監聽器
finishBeanFactoryInitialization(beanFactory)例項化剩餘非懶載入Bean
finishRefresh()事件釋出
resetCommonCaches()重新整理快取
就這樣我們的Bean工廠就建立完成了。看著如此簡單吧。後面我們來詳細看一下。內部還有超多的東西。Spring原始碼不建議太過於深入的學習,容易陷進去....
最近搞了一個個人公眾號,會每天更新一篇原創博文,java,python,自然語言處理相關的知識有興趣的小夥伴可以關注一下。