org.springframework.core简单分析

    xiaoxiao2024-05-18  95

    这个包的类主要用于spring框架的异常处理和一些核心的助手类(与框架具体部分无关的)。     这个包中主要应用到了简单工厂模式,用于判断jdk版本,根据jdk版本不同提供不同的集合类、当前方法栈信息等。我们来看看是如何判断当前用户的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;     } } 直接获取系统的java.version属性来进行jdk版本的判断。而CollectionFactory依据这个类来创建不同的集合类型,如果是jdk1.4就优先使用jdk1.4的集合框架,再次选择Commons Collections,最后才不得已就使用jdk1.3的集合框架,这里比较有趣的是判断Commons Collections的方法就是尝试Class.forName一个Commons集合框架中的对象,如果成功,当然证明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()方法用以获取最优版本的集合类型,比如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 也都是工厂类。可以看到,一个优秀的通用框架对于版本的兼容性非常重视。     这个包中另外一个需要注意的就是用于spring AOP功能实现的辅助类——ControlFlow。ControlFlow按照rod johnson的说法就是用于获取当前调用的方法栈的具体信息。ControlFlow是一个接口,拥有3个方法用于判断当前方法栈的位置: public   interface  ControlFlow {      /**       查找当前方法调用是否则在某类中      *  @param  clazz the clazz to look for       */      boolean  under(Class clazz);      /**      * 查找当前方法调用是否则在某类的某个方法中      * 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);      /**      * 当前栈帧是否包含传入的记号      *  @param  token the token to look for       */      boolean  underToken(String token); } 然后根据jdk版本的不同采用不同的方式实现这个接口:Jdk14ControlFlow和Jdk13ControlFlow。这是典型的 策略模式的应用。需要注意的是,这两个具体类的是放在工厂类ControlFlowFactory中作为内部类实现的: public   abstract   class  ControlFlowFactory {         static   class  Jdk13ControlFlow  implements  ControlFlow {             static   class  Jdk14ControlFlow  implements  ControlFlow {     } 在这里,我们可以学到的东西就如何去判断当前方法栈的信息?jdk1.4之前只能通过对StackTrace的字符串进行分析,而jdk1.4引入了java.lang.StackTraceElement用于获取当前方法调用所处的栈帧的信息,看看spring的使用方法,相当简单: 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 ;         } }

    获取当前栈帧的信息,对于一般的java开发者没有什么意义,对于AOP的实现和框架开发者可能有比较重要的作用,我还未研读spring的aop部分,不敢妄言,留待以后解答,如果您已经研读过这部分代码,不吝赐教。 这个包另外的一个特点就是将java的反射API演示了一遍,特别是Constant.java(用于提取某个类public static final定义的常量)和ReflectiveVisitorHelper (反射助手类),对于学习java反射技术也有不小的帮助。

    文章转自庄周梦蝶  ,原文发布时间5.17

    最新回复(0)