关于事务( Transation ),大家肯定都不陌生了,因为作为一个 Web 程序开发人员来说,我们一般都会和数据库打交道,然后对数据库中的数据进行一系列的操作,那么为了保证我们对数据操作的合理性我们就不能不用到事务,虽然事务的实现不需要我们去操心,但是我们还是需要对事务进行一些了解,这样我们才能够明白我们日常所使用的东西,比如我们常用的开源框架 Spring 、 Hibernat 等都会涉及到事务的问题,虽然事务有很多不同的实现,如符合 JTA 的事先, JDBC 的实现等等,但是其原理都是差不多的。
对于事务的理解,这个我觉得有必要说一下,一般大家看到的理解都是很正式的、书面的,有时候让人觉得有些乱,并且细节的东西太多,在这里我就不说说课贴书了,呵呵,那我就把我自己的一点理解说一下:刚接触到事务的时候,感觉还有些模糊,慢慢的感觉清晰了一些,事务是为了什么而产生的呢?就是为了对付并发而造成的对数据的修改以及读取时的错误(或者说是一些不正常的现象),如果没有并发,没有资源的同时访问,估计也就用不到事务这个玩意了,呵呵,就像我们在单击上使用的单用户的软件一样,应该不会用到事务吧,一般又没有人跟你争,控制个啥子啊!我觉得事务就可以这么理解。
而对于事务的分类,一般分为本地事务,即一个数据库的情况;再一个就是全局事务,也就是多个数据库的情况(其数据库事务的控制称为 XA ),具体的情况可以看下面几个链接的介绍:
http://blog.csdn.net/ladofwind/archive/2006/09/08/1194812.aspx 关于数据库事务的基本概念
http://www.huihoo.com/middleware/trade_middleware.html 里面有介绍关于 XA 的内容
http://www.javaeye.com/topic/6302 对跨数据库事务的一些讨论(总结一下就是一般采用两阶段提交的方式来解决跨数据库的事务问题)
http://msdn2.microsoft.com/zh-cn/library/ckawh9ct(VS.80).aspx MS 的关于单阶段和多阶段事务的提交的一些说明文档
并且还要支持 XA 的数据库连接池,开源的如 XAPool 等。
要说的就是这么多了,估计也基本够在 Web 开发中对其有一个了解 ~ 如果有更加深入的内容再进行讨论和补充。
今天感觉还是有必要再理解一下 Java Reflection 。
在说 Reflection 之前,我感觉还是先对静态语言和动态语言有一个了解比较好,下面来看一下一些资料:
1 、 http://cavingdeep.cnblogs.com/archive/2005/08/03/206374.html 说明了什么是静态的,什么是动态的,总结一下就是:
动态语言,准确地说,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化。比如众所周知的 ECMAScript(JavaScript) 便是一个动态语言。除此之外如 Ruby 、 Python 等也都属于动态语言,而 C 、 C++ 等语言则不属于动态语言。(通俗的说法就是:静态的是事先进行规划,考虑到后面需要做的一些事情;而动态的是管他后面会是怎么样呢,先开始再说,要的就是速度,呵呵,这有点和我们生活中做人做事的方式有些相似 ~ )
2 、 http://www.javaeye.com/topic/35763 对动态语言和静态语言的一个比较新颖的认识,主要从内存的分配和利用情况来说的,也就是说:动态语言不事先分配内存,到用的时候再说,而静态语言会先分配内存,并进行检查,大了放不下啊,呵呵
3 、 http://robbin.javaeye.com/blog/33971 讨论了静态语言和动态语言在开发方面的优势和使用情况等,还在讨论中,不好定论。
注:一般来说,静态语言比较容易调试,而动态语言不太容易调试,因为变数太多,呵呵。
由于静态语言不够灵活,再加上现在随着系统的扩大,以及框架建立的需要,所以说静态语言也需要越来越多的动态的特性,而作为现在首当其冲的 Java 语言,也要通过反射,在执行期间做一些动态的调整以适应多变的需求。
在 Reflection 机制中,最重要的一个类就是 Class 类,这里面记录了我们所定义的 class 中的一些信息,我们可以通过其获得我们定义的 变量、方法、构造函数以及父类等等,并且可以动态的对其进行调用,这样就可以在某些时候将我们没有事先设计的代码在运行期间执行,而不对原有的程序进行改变。
具体的使用样例可以参考: Core Java 2 第六、七版,或者侯捷的 java Reflection 教程(下载地址:http://www.blogjava.net/Files/wqhtomcat/Java反射机制-javatwo-2004-reflection.rar)。
1、 java 范型的实现原理: Java 语言中的泛型基本上完全在编译器中实现,由编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码。这种实现技术称为擦除( erasure )(编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除),所以说其实 java 的所谓的范型知识形式上的,仅仅是在编译期做了手脚,生成了一些标明范型的变量,应为这些都是编译期的行为,那么引用 buaawhl 的一句话就是说: java 只能支持 Field, Method 的 generic type 信息,这些信息存放在 class 文件的 contant pool 中,作为字符串常量出现,标志是 signature 。
2、 由于 Java 范型的实现采用的是 Erasure 方式,仅仅是在编译期进行检查,所以在运行过程中我们就不能进行范型的实例化,因为我们不知道到底要实例化什么类型的对象,与原来我们手动进行强制类型转换的一样,我们如果知道我们能够转换成什么对象,那么我们就可以将我们知道的类型的信息传递过去,也就是吧 XX.class 传递过去,这样 jvm 就知道我们要实例化什么样的对象了。
3、 原来 Class<T> 表示的是一个范型的 Class 类啊,为什么搞的像 List<T> 样式的范型声明呢?搞得我迷糊了好长时间,一致以为是一个类似容器的东西呢,这个语法感觉到有些奇怪,见笑了:),这个类一般用来接受 XX.class 返回的对象。
4、 要想在 java 中范型用得爽,还得配合使用反射才行啊。由于 Java 采用了擦拭法进行范型的支持,所以我们依旧不能在运行期获取到具体的类型的信息,而至能够在我们进行设计的时候对其类型信息进行指定,那么我们指定的类型的信息就可以存放在编译后生成的 class 文件中了,我们可以通过反射来获取到具体的存放的信息,要获取到动态的传入的信息就不行了。
如下所示:
定义一个超类:
再定义一个子类:
那么我们只能够获得我们实现定义好的要传入到 SuperClass 类中的 Integer 类型的范型信息,而不能得到我们在程序中传入的 Shit 类的类型信息,因为 java 范型的信息不记录的实例中,仅仅在类中进行了记录(这点感觉 java 的范型还不够成熟,可能因为要向后兼容等原因吧)。
参考资料:
http://www.duduwolf.com/wiki/2006/51.html
http://calvin.javaeye.com/blog/33139 白衣的 SpringSide 中对范型使用的说明
http://www-128.ibm.com/developerworks/cn/java/j-jtp01255.html Java 理论和实践关于范型的讲解
http://www.nirvanastudio.org/java/dont-repeat-the-dao.html 范型实现可重用 DAO 的文章
http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments()
http://buaawhl.javaeye.com/blog/22020 范型的实现原理,讲的比较清楚