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

很高兴再次看到各位
今天呢,我饶有兴趣的看了一点三国演义的前一部分,当时的曹操还不算上一个能权倾朝野的大人物,但是他忠肝义胆,在刺杀董卓失败后毅然加入了诸侯反抗董卓的大军当中,奋勇杀敌,但是这些反抗的军团内部斗争相当激烈,曹操在眼看着眼下的反抗军团无望的时候,毅然决然的选择了离开,并最终走到了丞相的位置。
我不得不说,在当时的社会当中,或许曹操的挟天子以令诸侯也是一个明义之举,因为当时皇帝无能,如果没有一个强有力的统治者,国家很可能会出现四分五裂的局面,虽然曹操当时能够勉强的控制住局面,但是,从历史的角度来说,当时的分裂已经是不可避免的了,我们可以说曹操是一个奸臣,但是如果没有曹操呢,那么很可能那时候的汉献帝早早的被废,然后各个诸侯各自为王,那么这个局面是更加混乱不堪的,所以群龙无首比有着一个算不上好人的统治者更加的危险
刚刚说了一点题外话啦,也算是本人有感而发吧,毕竟对于一个爱国爱党爱人民的新社会好青年来说,这个也是应该思考的嘛。。。。
那么,开始切入主题了
今天呢,我们主要讲的就是org.springframework.core.io.ClassPathResource类,让大家欣赏一下spring框架中的另一个经典
首先呢,在这个框架中,有三个字段
private final String path;  //文件的路径
private ClassLoader classLoader;   //类加载器
private Class<?> clazz;   //类文件
在这三个字段当中,path字段存放着文件的路径信息,不过不要以为有了这个路径,咱们就可以在path中存放目录,在class中申明类文件,事实上却没有那么简单,
首先,我们要明确一点,如果在clazz为null的情况下,在这个类中的各种逻辑是由classLoader实现的,但是如果clazz文件不为null,不管classLoader是否为null,事实上都是由clazz决定的,所以对于是否加clazz文件,一定要慎重
那么,可能有人会问了,如果要是按照这种情况来说的话,那么单独只用classLoader或者clazz不就可以了吗
但是这里也有一点小小的差别,就是clazz文件仅仅用在和clazz文件在同一个包中的文件,而classLoader相反,所以呢,也就是说,当clazz为null的情况下,我们应该以类路径为准(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
                

猜你喜欢

转载自liu75675231.iteye.com/blog/1961709