博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
org.springframework.core简单分析
阅读量:6381 次
发布时间:2019-06-23

本文共 5148 字,大约阅读时间需要 17 分钟。

  这个包的类主要用于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 {
   dot.gifdot.gif
   
static
 
class
 Jdk13ControlFlow 
implements
 ControlFlow {
  
   dot.gifdot.gif
    
static
 
class
 Jdk14ControlFlow 
implements
 ControlFlow {
   dot.gifdot.gif
}
在这里,我们可以学到的东西就如何去判断当前方法栈的信息?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

转载地址:http://cehqa.baihongyu.com/

你可能感兴趣的文章
[置顶] android 自定义ListView实现动画特效
查看>>
机器学习A-Z~Logistic Regression
查看>>
聊聊flink的NetworkEnvironmentConfiguration
查看>>
【Go】strings.Replace 与 bytes.Replace 调优
查看>>
RSA签名的PSS模式
查看>>
c# 注销 代码
查看>>
ubuntu 安装-apache2-trac-ldap【验证】-svn-mysql
查看>>
Nginx 安装
查看>>
php GD库
查看>>
项目管理
查看>>
隐私政策
查看>>
二分搜索树
查看>>
[折半查找]排序数组中某个元素出现次数
查看>>
【11-01】Sublime text 学习笔记
查看>>
.wav file research
查看>>
Link-Cut-Tree题目泛做(为了对应自己的课件)
查看>>
关于Android热点模式下的UDP广播
查看>>
多态-典型用法
查看>>
学习笔记之pandas Foundations | DataCamp
查看>>
C++编程练习(14)-------“单例模式”的实现
查看>>