org.springframework.core简单分析

简介:
  这个包的类主要用于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


目录
相关文章
|
Java Maven
程序包org.springframework.transaction.annotation不存在
整合ssm报:程序包org.springframework.transaction.annotation不存在 使用注解: @Transactional 之后,就一直报不存在 最终找到原因是:maven依赖 spring-tx版本问题,换个版本就OK
1675 0
程序包org.springframework.transaction.annotation不存在
|
6月前
|
存储 Java 关系型数据库
java: 无法访问org.springframework.context.ConfigurableApplicationContext
`亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍报错以及配置用处,根本不懂照抄那些配置是干啥的,稀里糊涂的按照博客搭完也跑不起来,因此记录这个。` `项目背景`:公司项目当前采用http协议+shiro+mysql的登录认证方式,而现在想支持ldap协议认证登录然后能够访问自己公司的项目网站。 `举例说明`:假设我们公司有自己的门户网站,现在我们收购了一家公司,他们数据库采用ldap存储用户数据,那么为了他们账户能登陆我们公司项目所以需要集成,而不是再把他们的账户重新在mysql再创建一遍,万一人家有1W个账户呢,不累死了且也不现实啊。
133 11
|
6月前
|
存储 Java 关系型数据库
java: 无法访问org.springframework.ldap.core.LdapTemplate
`亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍报错以及配置用处,根本不懂照抄那些配置是干啥的,稀里糊涂的按照博客搭完也跑不起来,因此记录这个。` `项目背景`:公司项目当前采用http协议+shiro+mysql的登录认证方式,而现在想支持ldap协议认证登录然后能够访问自己公司的项目网站。 `举例说明`:假设我们公司有自己的门户网站,现在我们收购了一家公司,他们数据库采用ldap存储用户数据,那么为了他们账户能登陆我们公司项目所以需要集成,而不是再把他们的账户重新在mysql再创建一遍,万一人家有1W个账户呢,不累死了且也不现实啊。
38 1
|
9月前
|
监控 前端开发 Java
深入理解 org.springframework.web.servlet.AsyncHandlerInterceptor
深入理解 org.springframework.web.servlet.AsyncHandlerInterceptor
121 0
|
10月前
解决The injection point has the following annotations:@org.springframework.beans.factory.annotation错误~
解决The injection point has the following annotations:@org.springframework.beans.factory.annotation错误~
1401 0
解决:org.springframework.web.method.annotation.MethodArgumentTypeMismatchExceptio
解决:org.springframework.web.method.annotation.MethodArgumentTypeMismatchExceptio
527 0
org.springframework.beans.NotWritablePropertyException
<div style="font-family:微软雅黑; font-size:14px; line-height:21px; widows:auto"> <div style="background-color:inherit">Spring属性注入异常</div> <div style="background-color:inherit"><br style="background
14307 0
|
网络安全
SSH框架整合遇到的错误——org.springframework.beans.NotWritablePropertyException:
提示错误信息: Unable to instantiate Action, userAction, defined for 'user_registPage' in namespace '/'Error creating bean with name 'userAction' defined in class path resource [applicationContext.
1660 0
Aurora-hec4.0_scaninvoice_异常_04_org.springframework.beans.factory.BeanNotOfRequiredTypeException
    二、参考资料 1.解决: org.springframework.beans.factory.BeanNotOfRequiredTypeException办法 2.
938 0
|
Java 数据格式 容器
org.springframework.web.context.ContextLoaderListener
在web.xml里面会配置一个listener和一个dispatcher
4854 0

热门文章

最新文章