Spring源碼閱讀

參考資料:spring源碼深度解析
Spring版本:Spring-4.3.5-RELEASE

吐槽下歧匈,老外寫的東西真暈啊,像親媽一樣啰啰嗦嗦幫你考慮了各種情況放仗,然后最好還不忘加一句:
如果你不滿意留夜,還可以拓展!E】取伯顶!

1.spring 核心代碼

1.1 核心流程初始化過程

非常清晰的模板方法,每一個(gè)步驟封裝成一個(gè)具體的函數(shù)進(jìn)行代理骆膝,職責(zé)清晰明了砾淌;

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      //預(yù)熱,做準(zhǔn)備工作
      prepareRefresh();
 
      // Tell the subclass to refresh the internal bean factory.
      //獲取內(nèi)部的bean factory
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 
      // Prepare the bean factory for use in this context.
      //預(yù)熱beanFactory
      prepareBeanFactory(beanFactory);
 
      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);
 
         // Invoke factory processors registered as beans in the context.
         //beanFactory在上下文中注冊bean谭网,核心的代碼就在這里
         invokeBeanFactoryPostProcessors(beanFactory);
 
         // Register bean processors that intercept bean creation.
         // bean創(chuàng)建的時(shí)候攔截并注冊bean處理器汪厨,這里只創(chuàng)建處理器,真正的創(chuàng)建是在getBean(..)方法里
         registerBeanPostProcessors(beanFactory);
 
         // Initialize message source for this context.
         // 用于支持國際化愉择,比如一些日志的國際化匹配等劫乱;
         initMessageSource();
 
         // 為上下文初始化消息傳播工具
         initApplicationEventMulticaster();
 
         // Initialize other special beans in specific context subclasses.
         // 鉤子方法:額外的beans處理方法
         onRefresh();
 
         // Check for listener beans and register them.
         // 注冊監(jiān)聽器
         registerListeners();
 
         // Instantiate all remaining (non-lazy-init) singletons.
         // 實(shí)例化非延時(shí)加載的bean單例
         finishBeanFactoryInitialization(beanFactory);
 
         // Last step: publish corresponding event.
         // push beans創(chuàng)建完成的消息
         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();
      }
   }
}

1.2 spring 類加載的基本類spring DefaultListableBeanFactory UML示意圖:

image.png

1.3 spring bean 創(chuàng)建過程

  • 轉(zhuǎn)換beanName
  • 嘗試從緩存中獲取單例
  • bean本身的實(shí)例化
  • 原型模式依賴檢測
  • parentBeanFactory 檢測
  • 將gernerecBeanDefinition 轉(zhuǎn)換成 RootBeanDefination
  • 尋找依賴
  • 根據(jù)scope 初始化(init)對應(yīng)的bean
  • 類型轉(zhuǎn)換
/**
 * Return an instance, which may be shared or independent, of the specified bean.
 * @param name the name of the bean to retrieve
 * @param requiredType the required type of the bean to retrieve
 * @param args arguments to use when creating a bean instance using explicit arguments
 * (only applied when creating a new instance as opposed to retrieving an existing one)
 * @param typeCheckOnly whether the instance is obtained for a type check,
 * not for actual use
 * @return an instance of the bean
 * @throws BeansException if the bean could not be created
 */
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
      final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      throws BeansException {
 
   //轉(zhuǎn)換beanName,我們知道在spring中锥涕,bean factory的名稱都是類似于 &org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
   //因此獲取的時(shí)候需要進(jìn)行轉(zhuǎn)換
   final String beanName = transformedBeanName(name);
   Object bean;
 
   // Eagerly check singleton cache for manually registered singletons.
   // 嘗試從緩存中獲取單例
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      if (logger.isDebugEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      //實(shí)例化
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
 
   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      // 檢測當(dāng)前依賴的類是否正在創(chuàng)建衷戈,如果是,則拋出異常
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }
 
      // Check if bean definition exists in this factory.
      // 如果bean配置不存在則只能去父工廠找
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
      }
 
      if (!typeCheckOnly) {
     
         markBeanAsCreated(beanName);
      }
 
      try {
         //轉(zhuǎn)換并合并BeanDefinition屬性
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);
 
         // Guarantee initialization of beans that the current bean depends on.
         // 原型模式的bean需要循環(huán)檢測依賴  防止出現(xiàn)A->B->A 的循環(huán)依賴情況出現(xiàn)
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               getBean(dep);
            }
         }
 
         // Create bean instance.
         // 創(chuàng)建bean實(shí)例
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
               @Override
               public Object getObject() throws BeansException {
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  catch (BeansException ex) {
                     // Explicitly remove instance from singleton cache: It might have been put there
                     // eagerly by the creation process, to allow for circular reference resolution.
                     // Also remove any beans that received a temporary reference to the bean.
                     destroySingleton(beanName);
                     throw ex;
                  }
               }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         }
 
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }
 
         else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                  @Override
                  public Object getObject() throws BeansException {
                     beforePrototypeCreation(beanName);
                     try {
                        return createBean(beanName, mbd, args);
                     }
                     finally {
                        afterPrototypeCreation(beanName);
                     }
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
            catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope '" + scopeName + "' is not active for the current thread; consider " +
                     "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                     ex);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }
 
   // Check if required type matches the type of the actual bean instance.
   // 轉(zhuǎn)換bean類型
   if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
      try {
         return getTypeConverter().convertIfNecessary(bean, requiredType);
      }
      catch (TypeMismatchException ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
} 

1.4 spring事務(wù)隔離級別及事務(wù)傳播實(shí)現(xiàn)

  • propagation_requierd(spring的事務(wù)默認(rèn)是該級別):如果當(dāng)前沒有事務(wù)层坠,就新建一個(gè)事務(wù)殖妇,如果已存在一個(gè)事務(wù)中,加入到這個(gè)事務(wù)中破花,這是最常見的選擇谦趣。
  • propagation_supports:支持當(dāng)前事務(wù)疲吸,如果沒有當(dāng)前事務(wù),就以非事務(wù)方法執(zhí)行前鹅。
  • propagation_mandatory:使用當(dāng)前事務(wù)摘悴,如果沒有當(dāng)前事務(wù),就拋出異常舰绘。
  • propagation_required_new:新建事務(wù)蹂喻,如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起捂寿。
  • propagation_not_supported:以非事務(wù)方式執(zhí)行操作口四,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起秦陋。
  • propagation_never:以非事務(wù)方式執(zhí)行操作窃祝,如果當(dāng)前事務(wù)存在則拋出異常。
  • propagation_nested:如果當(dāng)前存在事務(wù)踱侣,則在嵌套事務(wù)內(nèi)執(zhí)行粪小。如果當(dāng)前沒有事務(wù),則執(zhí)行與propagation_required類似的操作
 * Create a TransactionStatus for an existing transaction.
 */
private TransactionStatus handleExistingTransaction(
      TransactionDefinition definition, Object transaction, boolean debugEnabled)
      throws TransactionException {
 
    //若為非事務(wù)方式抡句,則拋異常
   if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
      throw new IllegalTransactionStateException(
            "Existing transaction found for transaction marked with propagation 'never'");
   }
    
   // 若存在事務(wù)探膊,掛起適當(dāng)前事務(wù)
   if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
      if (debugEnabled) {
         logger.debug("Suspending current transaction");
      }
      // 掛起當(dāng)前事務(wù)
      Object suspendedResources = suspend(transaction);
      boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
      return prepareTransactionStatus(
            definition, null, false, newSynchronization, debugEnabled, suspendedResources);
   }
    
   // 掛起當(dāng)前事務(wù),并新建事務(wù)
   if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
      if (debugEnabled) {
         logger.debug("Suspending current transaction, creating new transaction with name [" +
               definition.getName() + "]");
      }
      //掛起當(dāng)前事務(wù)
      SuspendedResourcesHolder suspendedResources = suspend(transaction);
      try {
         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
         DefaultTransactionStatus status = newTransactionStatus(
               definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
         // 重新開啟事務(wù)
         doBegin(transaction, definition);
         prepareSynchronization(status, definition);
         return status;
      }
      catch (RuntimeException beginEx) {
         resumeAfterBeginException(transaction, suspendedResources, beginEx);
         throw beginEx;
      }
      catch (Error beginErr) {
         resumeAfterBeginException(transaction, suspendedResources, beginErr);
         throw beginErr;
      }
   }
     
   // 若當(dāng)前事務(wù)存在待榔,則嵌套執(zhí)行事務(wù)
   if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
      if (!isNestedTransactionAllowed()) {
         throw new NestedTransactionNotSupportedException(
               "Transaction manager does not allow nested transactions by default - " +
               "specify 'nestedTransactionAllowed' property with value 'true'");
      }
      if (debugEnabled) {
         logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
      }
      // 判定是否支持事務(wù)備份點(diǎn)
      if (useSavepointForNestedTransaction()) {
         // Create savepoint within existing Spring-managed transaction,
         // through the SavepointManager API implemented by TransactionStatus.
         // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
         DefaultTransactionStatus status =
               prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
         // 創(chuàng)建備份點(diǎn)
         status.createAndHoldSavepoint();
         return status;
      }
      else {
         // Nested transaction through nested begin and commit/rollback calls.
         // Usually only for JTA: Spring synchronization might get activated here
         // in case of a pre-existing JTA transaction.
         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
         DefaultTransactionStatus status = newTransactionStatus(
               definition, transaction, true, newSynchronization, debugEnabled, null);
         // 不支持備份點(diǎn)的情況下會新建事務(wù)
         doBegin(transaction, definition);
         prepareSynchronization(status, definition);
         return status;
      }
   }
 
   // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
   if (debugEnabled) {
      logger.debug("Participating in existing transaction");
   }
   if (isValidateExistingTransaction()) {
      if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
         Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
         if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
            Constants isoConstants = DefaultTransactionDefinition.constants;
            throw new IllegalTransactionStateException("Participating transaction with definition [" +
                  definition + "] specifies isolation level which is incompatible with existing transaction: " +
                  (currentIsolationLevel != null ?
                        isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
                        "(unknown)"));
         }
      }
      if (!definition.isReadOnly()) {
         if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
            throw new IllegalTransactionStateException("Participating transaction with definition [" +
                  definition + "] is not marked as read-only but existing transaction is");
         }
      }
   }
   boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
   return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

2.1 一些干貨

2.1.1 aop注入的實(shí)現(xiàn)過程

doCreateBean中會暴露一個(gè)bean引用逞壁,用以處理循環(huán)引用;同時(shí)大家熟知的AOP就是通過getEarlyBeanReference(..)方法植入的锐锣;具體的腌闯,是在wrapIfNecessary(..) 方法中封裝了advice并創(chuàng)建了代理;

image.png

image.png

2.1.2 @Autowired注解的實(shí)現(xiàn)

image.png

doCreateBean(..)中的populateBean(..)方法雕憔,實(shí)現(xiàn)了基于@Autowired注解的實(shí)現(xiàn)姿骏,根據(jù)名稱或類型進(jìn)行依賴的注入;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末斤彼,一起剝皮案震驚了整個(gè)濱河市分瘦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌琉苇,老刑警劉巖嘲玫,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異并扇,居然都是意外死亡去团,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來土陪,“玉大人昼汗,你說我怎么就攤上這事⊥梗” “怎么了乔遮?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵扮超,是天一觀的道長取刃。 經(jīng)常有香客問我,道長出刷,這世上最難降的妖魔是什么璧疗? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮馁龟,結(jié)果婚禮上崩侠,老公的妹妹穿的比我還像新娘。我一直安慰自己坷檩,他們只是感情好却音,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矢炼,像睡著了一般系瓢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上句灌,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天夷陋,我揣著相機(jī)與錄音,去河邊找鬼胰锌。 笑死骗绕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的资昧。 我是一名探鬼主播酬土,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼格带!你這毒婦竟也來了诺凡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤践惑,失蹤者是張志新(化名)和其女友劉穎腹泌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尔觉,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凉袱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片专甩。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钟鸵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涤躲,到底是詐尸還是另有隱情棺耍,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布种樱,位于F島的核電站蒙袍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嫩挤。R本人自食惡果不足惜害幅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岂昭。 院中可真熱鬧以现,春花似錦、人聲如沸约啊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恰矩。三九已至记盒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間枢里,已是汗流浹背孽鸡。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栏豺,地道東北人彬碱。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像奥洼,于是被迫代替她去往敵國和親巷疼。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容