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

时间: 2024-08-30 10:25:46

org.springframework.core简单分析的相关文章

org.springframework.core.io包的类图

    org.springframework.core.io包中主要是各样的Resource类,Spring的 Resource 接口是为了提供更强的访问底层资源能力的抽象.具体的用法参考spring reference.这个包的类图非常简单,已经有人画的很清晰了,我直接拿过来,来自:Spring代码赏析:Resource类层次 相当巧妙的地方在于,为何AbstractResource的子类有的override了getFile()而有的没有?这是因为在AbstractResource的getF

linux中crontab的打core问题分析

接到同事报障, 程序又crash了, 但是找不到core, 而且是应该产生core的, 系统肯定哪里又有bug了. 先从系统层面大概都巡查了一下: 1.  找到别的程序的pid号,然后cat /proc/pid/limits  |grep core,返回Max core file size        0            unlimited            bytes, 有大问题, Soft Limit值居然是0, 继续找原因. 2.  用程序用户执行ulimit -c, 返回un

jquery的相关内容:jquery的简单分析

文章简介:jquery原理的简单分析,扒开jquery的小外套. 引言 最近LZ还在消化系统原理的第三章,因此这部分内容LZ打算再沉淀一下再写.本次笔者和各位来讨论一点前端的内容,其实有关jquery,在很久之前,LZ就写过一篇简单的源码分析.只不过当时刚开始写博客,写的相对来讲比较随意,直接就把源码给贴上来了,尽管加了很多注释,但还是会略显粗糙. 这次LZ再次执笔,准备稍微规范一点的探讨一下jquery的相关内容. jquery的外衣 jquery是一个轻量级的JS框架,这点相信大部分人都听过

Rman操作简单分析

http://www.itpub.net/245264.html Rman操作简单分析 在我的上一篇文章中为大家演示了rman 备份恢复的一个特定例子.(参考:http://www.dbanotes.net/Oracle/Rman...lfile_howto.htm)rman 对dbms_backup.restore 的一些特定调用完梢酝üebug 分析出来.通过设置debug 模式,我们可以跟踪到大量的Log,从而为分析提供一定的说明.假定我们提交如下的命令:rman target /

简单分析针对搜索引擎优化的三个阶段

做SEO优化绝大部分的精力都会放在针对搜索引擎上面的优化,通常针对搜索引擎优化都有三个阶段,下面我们就来简单分析一下这三个阶段! 第一阶段:这是初始化的阶段,这个时期是搜索引擎对新网站的考察期,通常百度考察的比较严格,谷歌考察的比较宽松,此时搜索引擎会对网站的首页会优先收录,算是给站长们的鼓励,对于内容一般收录很少,排名也是镜花水月,看不清楚,搜索引擎的蜘蛛更是很少光顾,此时的优化主要是优化网站的代码,定时定量的更新网站内容,每天做少量的外链,当然这些外链质量要高一点,这个优化阶段大致要花费近一

简单分析新闻网站二级新闻列表的表现形式

一个好新闻二级列表能让读者最大可能地获取所需信息,其列表形式也体现了这个网的思想,下面选取了几个以新闻为主的网站为例,简单分析其二级列表的表现形式.他们分别是:新华网.金洋网 .南方网及大洋网. 1.新华网 每页显示量大,不提供翻页,页面长,不严格按时间分类,但近段时间的新闻会都会靠前显示,新闻标题以每组5条或10条分组显示,焦点新闻的列表以每组10条显示,且有部分新闻加粗显示表示权重大. 2.金洋网 计算机二级哪个最简单"> 不严格按时间排列,权重大的新闻会用实心方块在前面标识,其它的则

对SysAnti.exe病毒的简单分析

周一在2号实验楼323嵌入式实验室用U盘时发现有病毒,重启后发现刚启动时电脑就有病毒,看来还原卡没起作用.一时兴起打包了病毒文件回来研究下. 病毒文件名:SysAnti.exe 文件大小:52.5KB MD5:4B160901566108C6F89F21444CE503E7 PEID查壳信息: PEID显示是ASPack壳,这一款兼容性良好的老牌壳.不过估计用工具脱不了,OD载入时出错,看来经过特意加密防止反编译.我也懒得深入研究壳了,直接丢入虚拟机的XP,创建快照.打开Procmon和Tota

class org.springframework.core.type.classreading.ClassMetadataReadingVisitor has interface org.springframework.asm.ClassVisitor as super class

今天在工作中遇到了下面的问题: java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99) ~[spring-test-4.0.5.RELEASE.jar:4.0.5.RELEASE]

网口扫盲二:Mac与Phy组成原理的简单分析

网口扫盲二:Mac与Phy组成原理的简单分析 1. general 下图是网口结构简图.网口由CPU.MAC和PHY三部分组成.DMA控制器通常属于CPU的一部分,用虚线放在这里是为了表示DMA控制器可能会参与到网口数据传输中. 对于上述的三部分,并不一定都是独立的芯片,根据组合形式,可分为下列几种类型: CPU集成MAC与PHY; CPU集成MAC,PHY采用独立芯片; CPU不集成MAC与PHY,MAC与PHY采用集成芯片; 本例中选用方案二做进一步说明,因为CPU总线接口很常见,通常都会做