菜鸟的Spring 3.0学习之旅(2)

来源:互联网 发布:淘宝店铺有效经营6个月 编辑:程序博客网 时间:2024/06/16 11:09

很高兴再次看到各位

今天呢,我饶有兴趣的看了一点三国演义的前一部分,当时的曹操还不算上一个能权倾朝野的大人物,但是他忠肝义胆,在刺杀董卓失败后毅然加入了诸侯反抗董卓的大军当中,奋勇杀敌,但是这些反抗的军团内部斗争相当激烈,曹操在眼看着眼下的反抗军团无望的时候,毅然决然的选择了离开,并最终走到了丞相的位置。

我不得不说,在当时的社会当中,或许曹操的挟天子以令诸侯也是一个明义之举,因为当时皇帝无能,如果没有一个强有力的统治者,国家很可能会出现四分五裂的局面,虽然曹操当时能够勉强的控制住局面,但是,从历史的角度来说,当时的分裂已经是不可避免的了,我们可以说曹操是一个奸臣,但是如果没有曹操呢,那么很可能那时候的汉献帝早早的被废,然后各个诸侯各自为王,那么这个局面是更加混乱不堪的,所以群龙无首比有着一个算不上好人的统治者更加的危险

刚刚说了一点题外话啦,也算是本人有感而发吧,毕竟对于一个爱国爱党爱人民的新社会好青年来说,这个也是应该思考的嘛。。。。

那么,开始切入主题了

今天呢,我们主要讲的就是org.springframework.core.io.ClassPathResource类,让大家欣赏一下spring框架中的另一个经典

首先呢,在这个框架中,有三个字段

       private final String path;  //文件的路径

       private ClassLoader classLoader;   //类加载器

       private Class<?> clazz;   //类文件

在这三个字段当中,path字段存放着文件的路径信息,不过不要以为有了这个路径,咱们就可以在path中存放目录,在class中申明类文件,事实上却没有那么简单,

首先,我们要明确一点,如果在clazznull的情况下,在这个类中的各种逻辑是由classLoader实现的,但是如果clazz文件不为null,不管classLoader是否为null,事实上都是由clazz决定的,所以对于是否加clazz文件,一定要慎重

那么,可能有人会问了,如果要是按照这种情况来说的话,那么单独只用classLoader或者clazz不就可以了吗

但是这里也有一点小小的差别,就是clazz文件仅仅用在和clazz文件在同一个包中的文件,而classLoader相反,所以呢,也就是说,当clazznull的情况下,我们应该以类路径为准(WEB-INF/classes路径下面),clazz不为null的情况下,我们就不应该使用”/”符号,并且呢保证和clazz在一个包里面

然后,我让大家看看他的构造器

       public ClassPathResource(String path, ClassLoader classLoader) {

              Assert.notNull(path, "Path must not be null");

              String pathToUse = StringUtils.cleanPath(path);

              if (pathToUse.startsWith("/")) {     //如果相对路径的前面有斜杠,则删除

                     pathToUse = pathToUse.substring(1);

              }

              this.path = pathToUse;

              this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());

       }

public ClassPathResource(String path, Class<?> clazz) {

              Assert.notNull(path, "Path must not be null");

              this.path = StringUtils.cleanPath(path);

              this.clazz = clazz;

       }

protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {

              this.path = StringUtils.cleanPath(path);

              this.classLoader = classLoader;

              this.clazz = clazz;

       }

大家看了这三个构造器,说实话,我并不认为ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz)这个构造器有什么用,因为在这个类当中,如果clazz不为null,那么classLoader完全是没有什么用处的,举个例子

Org.springframework.core.io.ClassPathResource#exists()

public boolean exists() {

              URL url;

              if (this.clazz != null) {

                     url = this.clazz.getResource(this.path);

              }

              else {

                     url = this.classLoader.getResource(this.path);

              }

              return (url != null);

       }

恩恩,这个方法我想大家应该会明白我的意思了,但是exists()方法来说,它的标准和FileSystemResource又是不同的,在FileSystemResource中,目录是不可以当做文件存在的,但是在ClassPathResource中却是可以的,我不知道它最终的意思是什么,但是目前,让我看到的就是标准的不统一

另外,第一个构造器对于path有一个限制,就是路径的最前面不能是”/”,但是在后面的两个构造器却可以,我想这应该也是标准的不统一

当然了,在这个构造器里面,我发现了真正让我感到兴奋的语句,

String pathToUse = StringUtils.cleanPath(path);

这个语句的实现,对于我来说,我只能用欣赏两个字,

cleanPath方法里,主要的功能有两个,一个是吧里面的”\”转换成”/”,另一个作用,就是把里面的”.”,”..”都去掉,这个大家应该很好理解为什么,所以我也不详细说明了,但是这个却允许d:/../123/123.txt的形式,这个也是让我比较费解的东东啦,或许人家有更好的用处

另外,对于cleanPath()方法里的一个语句段,我是非常欣赏的

String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);  //吧路径按照"/"切割成一个个的String数组

              List<String> pathElements = new LinkedList<String>();

              int tops = 0;

 

              for (int i = pathArray.length - 1; i >= 0; i--) {

                     String element = pathArray[i];

                     if (CURRENT_PATH.equals(element)) {

                            //指向当前的目录-删掉 CURREMT_PATH=".";

                     }

                     else if (TOP_PATH.equals(element)) {

                            //注册已经找到的上层路径,TOP_PATH="..";

                            tops++;

                     }

                     else {

                            if (tops > 0) {

                                   //合并在上层路径中和元素一致的元素路径

                                   tops--;

                            }

                            else {

                                   //找到的普通的路径元素

                                   pathElements.add(0, element);

                            }

                     }

              }

首先呢,对于使用LinkedList的使用,我觉得是很明智的,不解释

然后呢,这个实现的主要思想就像是打扑克的时候,吧每张牌都放到牌的最下面,不符合条件的牌扔到一边,对于这种筛选的思想来说,我觉得是很值得提倡的

在上面的构造器里,大家应该会看到一个方法ClassUtils.getDefaultClassLoader()

它的具体实现如下

public static ClassLoader getDefaultClassLoader() {

              ClassLoader cl = null;

              try {

                     cl = Thread.currentThread().getContextClassLoader();

              }

              catch (Throwable ex) {

                     //不能使用线程上下文加载器-返回系统类加载器

              }

              if (cl == null) {

                     // No thread context class loader -> use class loader of this class.

                     //没有线程上下文类加载器->用类加载器加载这个类

                     cl = ClassUtils.class.getClassLoader();

              }

              return cl;

       }

大家可能会问了,我为什么要写这个呢?因为这里也有我比较疑惑的东西,那就是上下文类加载器和由类创建的类加载器有什么不同呢?我想,最大的不同可能就是创建者不同罢了,其实这个应该是一个不值得讨论的话题,所以不予多说

不过呢,在这里,我觉得比较令我诧异的方法应该就是getDescription了,因为经过我的测试,如果在clazz不为null的情况下,一致都达不到它的代码想要实现的效果

public String getDescription() {

              StringBuilder builder = new StringBuilder("class path resource [");

 

              if (this.clazz != null) { //经过我的测试,这个条件无效,或者只是在我这种条件下无效,有兴趣的朋友可以测试一下

                     builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));

                     builder.append('/');

              }

 

              builder.append(this.path);

              builder.append(']');

              return builder.toString();

       }

是不是今天这个有点吐槽吐的多了,或者叫班门弄斧,或者叫自不量力,反正我心里是这么想的:它不是圣经,不可能考虑的那么周全,我呢,也不是圣人,说的每句话都对,其实呢,心里真正明白对错的,应该是各位读者

好了,该睡觉觉去了,byebye

                                
原创粉丝点击