前言web
本文轉自「天河聊技術」微信公衆號spring
今天的主要內容是spring上下文刷新相關源碼解析設計模式
正文緩存
跟蹤到這個類微信
org.springframework.web.context.ContextLoader#configureAndRefreshWebApplicationContext這行代碼併發
// 上下文刷新 wac.refresh();
找到org.springframework.context.ConfigurableApplicationContext#refresh這個接口的一個抽象實現org.springframework.context.support.AbstractApplicationContext#refreshide
@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.初始化內部beanFactory TODO 天河 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(); } } }
總體看下,這個方法採用了門面設計模式,代碼看起來跟整潔,邏輯很清晰。post
刷新和銷燬上下文必須是同步的,這裏加了一個鎖ui
synchronized (this.startupShutdownMonitor) {
上下文刷新的前置工做this
prepareRefresh();
跟蹤到這個方法
org.springframework.context.support.AbstractApplicationContext#prepareRefresh spring上下文刷新以前的一些前置工做,主要是相關屬性的解析
protected void prepareRefresh() { this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } // Initialize any placeholder property sources in the context environment 解析佔位符 initPropertySources(); // Validate that all properties marked as required are resolvable // see ConfigurablePropertyResolver#setRequiredProperties // 驗證Required的屬性 getEnvironment().validateRequiredProperties(); // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); }
返回到這個方法org.springframework.context.support.AbstractApplicationContext#refresh
這一行代碼
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
建立beanFactory。
org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory跟蹤到這個方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 刷新beanFactory refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
刷新beanFactory
refreshBeanFactory();
跟蹤到這個方法org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory 實現了上下文底層的beanFactory刷新,若是以前有beanFactory就關閉並再初始化一個beanFactory。
@Override protected final void refreshBeanFactory() throws BeansException { // 若是存在beanFactory if (hasBeanFactory()) { // 銷燬bean destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
判斷是否存在beanFactory
if (hasBeanFactory()) { // 銷燬bean destroyBeans(); closeBeanFactory(); }
跟蹤到這個方法
org.springframework.context.support.AbstractApplicationContext#destroyBeans 銷燬單例的bean
protected void destroyBeans() { // 獲取beanFactory,並銷燬單例的bean TODO 銷燬bean getBeanFactory().destroySingletons(); }
找到這個方法
org.springframework.beans.factory.support.DefaultListableBeanFactory#destroySingletons
@Override public void destroySingletons() { super.destroySingletons(); // 清除記錄的單例beanName的緩存 this.manualSingletonNames.clear(); clearByTypeCache(); }
第一行代碼調用了父類的這個方法
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#destroySingletons
@Override public void destroySingletons() { super.destroySingletons(); // 清空beanFactory緩存 this.factoryBeanObjectCache.clear(); }
第一行代碼又調用了父類的這個方法
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingletons
public void destroySingletons() { if (logger.isDebugEnabled()) { logger.debug("Destroying singletons in " + this); } // 這裏使用ConcurrentHashMap本地緩存單例的bean實例,訪問次數比較多,提搞併發量 synchronized (this.singletonObjects) { this.singletonsCurrentlyInDestruction = true; } String[] disposableBeanNames; // 這裏是用LinkedHashMap本地緩存銷燬的bean實例 synchronized (this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1; i >= 0; i--) { // 銷燬單例的bean destroySingleton(disposableBeanNames[i]); } this.containedBeanMap.clear(); this.dependentBeanMap.clear(); this.dependenciesForBeanMap.clear(); // 同步清空緩存 synchronized (this.singletonObjects) { this.singletonObjects.clear(); this.singletonFactories.clear(); this.earlySingletonObjects.clear(); this.registeredSingletons.clear(); this.singletonsCurrentlyInDestruction = false; } }
找到這行代碼
destroySingleton(disposableBeanNames[i]);
進入到這個方法
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton
public void destroySingleton(String beanName) { // Remove a registered singleton of the given name, if any.刪除單例的bean,從本地緩存中刪除 removeSingleton(beanName); // Destroy the corresponding DisposableBean instance. DisposableBean disposableBean; synchronized (this.disposableBeans) { // 從本地緩存中刪除 disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); } // bean銷燬的邏輯 destroyBean(beanName, disposableBean); }
最後
本次介紹到這裏,以上內容僅供參考。下次bean銷燬的源碼解析。