莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          org.springframework.core簡單分析

          Posted on 2007-04-10 16:56 dennis 閱讀(4561) 評論(2)  編輯  收藏 所屬分類: java源碼解讀
              這個包的類主要用于spring框架的異常處理和一些核心的助手類(與框架具體部分無關(guān)的)。
              這個包中主要應(yīng)用到了簡單工廠模式,用于判斷jdk版本,根據(jù)jdk版本不同提供不同的集合類、當(dāng)前方法棧信息等。我們來看看是如何判斷當(dāng)前用戶的jdk版本的:

          package org.springframework.core;

          public class JdkVersion {
              
              
          public static final int JAVA_13 = 0;
              
              
          public static final int JAVA_14 = 1;
              
              
          public static final int JAVA_15 = 2;

              
          private static String javaVersion;

              
          private static int majorJavaVersion = JAVA_13;
              
              
          static {
                  javaVersion 
          = System.getProperty("java.version");
                  
          // should look like "1.4.1_02"
                  if (javaVersion.indexOf("1.4."!= -1) {
                      majorJavaVersion 
          = JAVA_14;
                  }
                  
          else if (javaVersion.indexOf("1.5."!= -1) {
                      majorJavaVersion 
          = JAVA_15;
                  }
                  
          // else leave as 1.3 default
              }

              
          /**
               * Return the full Java version string, as returned by
               * <code>System.getProperty("java.version")</code>.
               
          */
              
          public static String getJavaVersion() {
                  
          return javaVersion;
              }

              
          /**
               * Get the major version code. This means we can do things like
               * <code>if (getMajorJavaVersion() < JAVA_14)</code>.
               * 
          @return a code comparable to the JAVA_XX codes in this class
               * 
          @see #JAVA_13
               * 
          @see #JAVA_14
               * 
          @see #JAVA_15
               
          */
              
          public static int getMajorJavaVersion() {
                  
          return majorJavaVersion;
              }

          }

          直接獲取系統(tǒng)的java.version屬性來進(jìn)行jdk版本的判斷。而CollectionFactory依據(jù)這個類來創(chuàng)建不同的集合類型,如果是jdk1.4就優(yōu)先使用jdk1.4的集合框架,再次選擇Commons Collections,最后才不得已就使用jdk1.3的集合框架,這里比較有趣的是判斷Commons Collections的方法就是嘗試Class.forName一個Commons集合框架中的對象,如果成功,當(dāng)然證明classpath有commons-collections.jar包:
          static {
                  
          // Check whether JDK 1.4+ collections and/or
                  
          // Commons Collections 3.x are available.
                  if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_14) {
                      logger.info(
          "JDK 1.4+ collections available");
                  }
                  
          try {
                      Class.forName(COMMONS_COLLECTIONS_CLASS_NAME);
                      commonsCollections3xAvailable 
          = true;
                      logger.info(
          "Commons Collections 3.x available");
                  }
                  
          catch (ClassNotFoundException ex) {
                      commonsCollections3xAvailable 
          = false;
                  }
              }

          然后就是一系列的getXXXIfPossible()方法用以獲取最優(yōu)版本的集合類型,比如getLinkedHashMapIfPossible():
          public static Map createLinkedMapIfPossible(int initialCapacity) {
                  
          if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_14) {
                      logger.debug(
          "Creating [java.util.LinkedHashMap]");
                      
          return Jdk14CollectionFactory.createLinkedHashMap(initialCapacity);
                  }
                  
          else if (commonsCollections3xAvailable) {
                      logger.debug(
          "Creating [org.apache.commons.collections.map.LinkedMap]");
                      
          return CommonsCollectionFactory.createLinkedMap(initialCapacity);
                  }
                  
          else {
                      logger.debug(
          "Falling back to [java.util.HashMap] for linked map");
                      
          return new HashMap(initialCapacity);
                  }
              }
          其中的Jdk14CollectionFactory 和CommonsCollectionFactory 也都是工廠類。可以看到,一個優(yōu)秀的通用框架對于版本的兼容性非常重視。

              這個包中另外一個需要注意的就是用于spring AOP功能實(shí)現(xiàn)的輔助類——ControlFlow。ControlFlow按照rod johnson的說法就是用于獲取當(dāng)前調(diào)用的方法棧的具體信息。ControlFlow是一個接口,擁有3個方法用于判斷當(dāng)前方法棧的位置:
          public interface ControlFlow {

              
          /**
                查找當(dāng)前方法調(diào)用是否則在某類中
               * 
          @param clazz the clazz to look for
               
          */
              
          boolean under(Class clazz);

              
          /**
               * 查找當(dāng)前方法調(diào)用是否則在某類的某個方法中
               * according to the current stack trace.
               * 
          @param clazz the clazz to look for
               * 
          @param methodName the name of the method to look for
               
          */
              
          boolean under(Class clazz, String methodName);

              
          /**
               * 當(dāng)前棧幀是否包含傳入的記號
               * 
          @param token the token to look for
               
          */
              
          boolean underToken(String token);

          }

          然后根據(jù)jdk版本的不同采用不同的方式實(shí)現(xiàn)這個接口:Jdk14ControlFlow和Jdk13ControlFlow。這是典型的策略模式的應(yīng)用。需要注意的是,這兩個具體類的是放在工廠類ControlFlowFactory中作為內(nèi)部類實(shí)現(xiàn)的:
          public abstract class ControlFlowFactory {
             
             
          static class Jdk13ControlFlow implements ControlFlow {
            
             

              
          static class Jdk14ControlFlow implements ControlFlow {
             
          }

          在這里,我們可以學(xué)到的東西就如何去判斷當(dāng)前方法棧的信息?jdk1.4之前只能通過對StackTrace的字符串進(jìn)行分析,而jdk1.4引入了java.lang.StackTraceElement用于獲取當(dāng)前方法調(diào)用所處的棧幀的信息,看看spring的使用方法,相當(dāng)簡單:
          static class Jdk14ControlFlow implements ControlFlow {

                  
          private StackTraceElement[] stack;

                  
          public Jdk14ControlFlow() {
                      
          this.stack = new Throwable().getStackTrace();
                  }

                  
          /**
                   * Searches for class name match in a StackTraceElement.
                   
          */
                  
          public boolean under(Class clazz) {
                      Assert.notNull(clazz, 
          "Class must not be null");
                      String className 
          = clazz.getName();
                      
          for (int i = 0; i < stack.length; i++) {
                          
          if (this.stack[i].getClassName().equals(className)) {
                              
          return true;
                          }
                      }
                      
          return false;
                  }

                  
          /**
                   * Searches for class name match plus method name match
                   * in a StackTraceElement.
                   
          */
                  
          public boolean under(Class clazz, String methodName) {
                      Assert.notNull(clazz, 
          "Class must not be null");
                      Assert.notNull(methodName, 
          "Method name must not be null");
                      String className 
          = clazz.getName();
                      
          for (int i = 0; i < this.stack.length; i++) {
                          
          if (this.stack[i].getClassName().equals(className) &&
                                  
          this.stack[i].getMethodName().equals(methodName)) {
                              
          return true;
                          }
                      }
                      
          return false;
                  }

                  
          /**
                   * Leave it up to the caller to decide what matches.
                   * Caller must understand stack trace format, so there's less abstraction.
                   
          */
                  
          public boolean underToken(String token) {
                      
          if (token == null) {
                          
          return false;
                      }
                      StringWriter sw 
          = new StringWriter();
                      
          new Throwable().printStackTrace(new PrintWriter(sw));
                      String stackTrace 
          = sw.toString();
                      
          return stackTrace.indexOf(token) != -1;
                  }
          }

          獲取當(dāng)前棧幀的信息,對于一般的java開發(fā)者沒有什么意義,對于AOP的實(shí)現(xiàn)和框架開發(fā)者可能有比較重要的作用,我還未研讀spring的aop部分,不敢妄言,留待以后解答,如果您已經(jīng)研讀過這部分代碼,不吝賜教。

          這個包另外的一個特點(diǎn)就是將java的反射API演示了一遍,特別是Constant.java(用于提取某個類public static final定義的常量)和ReflectiveVisitorHelper (反射助手類),對于學(xué)習(xí)java反射技術(shù)也有不小的幫助。


          評論

          # re: org.springframework.core簡單分析  回復(fù)  更多評論   

          2007-04-11 11:53 by cresposhi
          不錯 up
          最近正在重讀Core Java
          對這些框架源代碼很有感覺。。。

          # re: org.springframework.core簡單分析  回復(fù)  更多評論   

          2007-04-11 14:44 by dennis
          @cresposhi
          呵呵,我也是最近閑著無聊就讀讀源碼,多謝關(guān)注
          主站蜘蛛池模板: 栖霞市| 扬中市| 勐海县| 涞水县| 资阳市| 衡南县| 卓资县| 望谟县| 墨竹工卡县| 布拖县| 乌兰察布市| 荔浦县| 甘肃省| 噶尔县| 炉霍县| 洛宁县| 乌审旗| 财经| 陆良县| 襄樊市| 五原县| 澄迈县| 汨罗市| 乌兰察布市| 靖宇县| 襄樊市| 酒泉市| 宽甸| 麦盖提县| 周至县| 梨树县| 民权县| 高州市| 沙雅县| 北川| 辽宁省| 乐昌市| 丹江口市| 雅江县| 青神县| 茌平县|