??xml version="1.0" encoding="utf-8" standalone="yes"?>国产爆初菊在线观看免费视频网站,久久91超碰青草在哪里看,超碰在线97国产http://www.aygfsteel.com/formatmyself/category/4446.htmlif(!java.isExist()) boss.fireOut(me);zh-cnTue, 27 Feb 2007 14:23:46 GMTTue, 27 Feb 2007 14:23:46 GMT60自己写了一个比较变态的c,试一下关于类初始化顺序的知识~http://www.aygfsteel.com/formatmyself/articles/30240.html早餐2?早餐2?Fri, 10 Feb 2006 18:03:00 GMThttp://www.aygfsteel.com/formatmyself/articles/30240.htmlhttp://www.aygfsteel.com/formatmyself/comments/30240.htmlhttp://www.aygfsteel.com/formatmyself/articles/30240.html#Feedback0http://www.aygfsteel.com/formatmyself/comments/commentRss/30240.htmlhttp://www.aygfsteel.com/formatmyself/services/trackbacks/30240.html    public Outer() {
        System.out.print("a");
    }
    public static void sayOther(String s){
        System.out.print(s);
    }
    public int say(String s){
        System.out.print(s);
        return 0;
    }
    {
        System.out.print("c");
        inner.innerMethed("d");
    }
    static
    {
        System.out.print("e");
        inner.innerMethed("f");
    }
    private int i=say("g");
    private static inner t= new inner();
    private inner tt=new inner();
    private innerOther ttt=new innerOther();
    static class inner{
        public inner(){
            System.out.print("h");
        }
        public static void innerMethed(String s){
            System.out.print(s);
        }
        {
            System.out.print("i");
        }
        static
        {
            System.out.print("j");
        }
    }
    class innerOther{
        public innerOther(){
            System.out.print("k");
        }
        {
            System.out.print("l");
        }
    }
    public static void main(String[] args) {
        System.out.print("m");
        Outer outer = new Outer();
        System.out.print("n");
    }
}



{案是:ejfihmcdgihlkan


早餐2? 2006-02-11 02:03 发表评论
]]>
StringcȝequalsҎ?=Ҏ的比?/title><link>http://www.aygfsteel.com/formatmyself/articles/27168.html</link><dc:creator>早餐2?</dc:creator><author>早餐2?</author><pubDate>Sun, 08 Jan 2006 11:24:00 GMT</pubDate><guid>http://www.aygfsteel.com/formatmyself/articles/27168.html</guid><wfw:comment>http://www.aygfsteel.com/formatmyself/comments/27168.html</wfw:comment><comments>http://www.aygfsteel.com/formatmyself/articles/27168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/formatmyself/comments/commentRss/27168.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/formatmyself/services/trackbacks/27168.html</trackback:ping><description><![CDATA[<P>先看下面的例?<BR>01: public class StringExample<BR>02: {<BR>03: public static void main (String args[])<BR>04:   {<BR>05: String s0 = "Programming";<BR>06: String s1 = new String ("Programming");<BR>07: String s2 = "Program" + "ming";<BR>08:<BR>09: System.out.println("s0.equals(s1): " + (s0.equals(s1)));<BR>10: System.out.println("s0.equals(s2): " + (s0.equals(s2)));<BR>11: System.out.println("s0 == s1: " + (s0 == s1));<BR>12: System.out.println("s0 == s2: " + (s0 == s2));   <BR>13:    }}<BR>q个例子包含? 个String 型变?其中两个被赋g帔R表达式“Programming?另一个被赋g一个新建的gؓ“Programming”的String cȝ实例。用equals(...)Ҏ和? =”运符q行比较产生了下列结?<BR>s0。equals(s1): true<BR>s0。equals(s2): true<BR>s0 == s1: false<BR>s0 == s2: true</P> <P>      String.equals()Ҏ比较的是字符串的内容,使用equals(...)Ҏ会对字符串中的所有字W一个接一个地q行比较,如果完全相等那么q回true?在这U情况下全部字符串都是相同的,所以当字符串s0 与s1 或s2 比较时我们得到的q回值均为true 。运符?=”比较的是String 实例的引用。在q种情况下很明显s0 和s1 q不是同一个String 实例,但s0 和s2 是同一个。读者也怼问s0 和s2 怎么是同一个对象呢Q?BR>      q个问题的答案来自于Java语言规范中关于字W串帔RString Literals 的章节。本例中“Programming?,“Program”和“ming”都是字W串帔R!!它们在编译期p定了当一个字W串由多个字W串帔Rq接而成?例如s2 ,它同样在~译期就被确定ؓ一个字W串帔R。Java 保一个字W串帔R只有一份拷?所以当Programming”和“Program?“ming”被定为值相{时,Java 会设|两个变量的引用为同一个常量的引用。在帔R池constant pool ?Java 会跟t所有的字符串常量?BR>       帔R池指的是在编译期被确?q被保存在已~译?class 文g中的一些数据。它包含了关于方?c?接口{等,当然q有字符串常量的信息。当JVM 装蝲了这?class 文g。变量s0 和s2 被确?JVM 执行了一名为常量池解析constant pool resolution 的操作。该Ҏ作针对字W串的处理过E包括下? 个步?摘自JVM 规范5? ?:<BR>       ¹ 如果另一个常量池入口constant pool entry 被标CؓCONSTANT_String2 ,q且指出同样的Unicode 字符序列已经被确?那么q项操作的结果就是ؓ之前的常?BR>池入口创建的String 实例的引用?BR>       ̔ 否则,如果intern()Ҏ已经被这个常量池描述的一个包含同样Unicode 字符序列的String 实例调用q了,那么q项操作的结果就是那个相同String 实例的引用?BR>      否则,一个新的String 实例会被创徏它包含了CONSTANT_String 入口描述的Unicode 字符;序列q个String 实例是该项操作的结果?BR>      也就是说,当常量池W一ơ确定一个字W串,在Java 内存栈中创Z个String 实例。在帔R池中,后来的所有针对同样字W串内容的引?都会得到之前创徏的String 实例。当JVM 处理到第6 行时,它创Z字符串常量Programming 的一份拷贝到另一个String 实例中。所以对s0 和s1 的引用的比较l果是false ,因ؓ它们不是同一个对象。这是Zs0==s1 的操作在某些情况下与s0.equals(s1)不同。s0==s1 比较的是对象引用的?而s0.equals(s1)实际上执行的是字W串内容的比较?BR>      存在?class 文g中的帔R?在运行期被JVM 装蝲,q且可以扩充。此前提到的intern()Ҏ针对String 实例的这个意图提供服务。当针对一个String 实例调用了intern()Ҏ,intern()Ҏ遵守前面概括的第3 步以外的帔R池解析规?因ؓ实例已经存在,而不需要另外创Z个新的。所以已存在的实例的引用被加入到该常量池。来看看另一个例?<BR>01: import java.io.*;<BR>02:<BR>03: public class StringExample2<BR>04: {<BR>05: public static void main (String args[])<BR>06:{<BR>07: String sFileName = "test.txt";<BR>08: String s0 = readStringFromFile(sFileName);<BR>09: String s1 = readStringFromFile(sFileName);<BR>10:<BR>11: System.out.println("s0 == s1: " + (s0 == s1));<BR>12: System.out.println("s0.equals(s1): " + (s0.equals(s1)));<BR>13:<BR>14: s0.intern();<BR>15: s1.intern();<BR>16:<BR>17: System.out.println("s0 == s1: " + (s0 == s1));<BR>18: System.out.println("s0 == s1.intern(): " +<BR>19: (s0 == s1.intern()));<BR>20: }<BR>21:<BR>22: private static String readStringFromFile (String sFileName)<BR>23: {<BR>24: //…read string from file?BR>25: }<BR>26: }<BR>     q个例子没有讄s0 和s1 的gؓ字符串常?取而代之的是在q行期它从一个文件中d字符?q把值分配给readStringFromFile(...)Ҏ创徏的String 实例。从W? 行开?E序对两个被新创Zؓh同样字符值的String 实例q行处理。当你看CW?1 行到12 行的输出l果?你会再次注意到这两个对象q不是同一?但它们的内容是相同的。输出结果如?<BR><BR>s0 == s1: false<BR>s0.equals(s1): true<BR>s0 == s1: false<BR>s0 == s1.intern(): true<BR>W?4 行所做的是将String 实例的引用s0 存入帔R池。当W?5 行被处理?对s1.intern()Ҏ的调?会简单地q回引用s0?q样一来第17 行和18 行的输出l果正是我们所期望?s0 与s1 仍旧是截然不同的两个String 。实例因此s0==s1 的结果是false?而s1.intern()q回的是帔R池中的引用值即s0 所,以表辑ּs0==s1.intern()的结果是true?假如我们希望实例s1 存入帔R池中,我们必须首先讄s0 为null, 然后h垃圾回收器garbagecollector 回收被指向s0 的String 实例。在s0 被回收后s1.intern()Ҏ的调?会把s1存入帔R池?BR>       ȝ来说在执行等式比较时,应该始终使用String.equals(...)Ҏ,而不?=q算W。如果你q是习惯性地使用==q算W?那么intern()Ҏ可以帮助你得到正的{案。因为当n 和m 均ؓString 实例的引用时,语句n.equals(m)与n.intern() ==m.intern()得到的结果是一致的。假如你打算充分利用帔R池的优势那么你就应该选择String.intern()Ҏ?/P> <P><BR> </P><img src ="http://www.aygfsteel.com/formatmyself/aggbug/27168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/formatmyself/" target="_blank">早餐2?</a> 2006-01-08 19:24 <a href="http://www.aygfsteel.com/formatmyself/articles/27168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java源码分析Q深入探讨Iterator模式http://www.aygfsteel.com/formatmyself/articles/27138.html早餐2?早餐2?Sun, 08 Jan 2006 06:39:00 GMThttp://www.aygfsteel.com/formatmyself/articles/27138.htmlhttp://www.aygfsteel.com/formatmyself/comments/27138.htmlhttp://www.aygfsteel.com/formatmyself/articles/27138.html#Feedback0http://www.aygfsteel.com/formatmyself/comments/commentRss/27138.htmlhttp://www.aygfsteel.com/formatmyself/services/trackbacks/27138.html
下面我们先简单讨Z个根接口CollectionQ然后分析一个抽象类AbstractList和它的对应Iterator接口Qƈ仔细研究q代子模式的实现原理?BR>
本文讨论的源代码版本是JDK 1.4.2Q因为JDK 1.5在java.util中用了很多泛型代码Qؓ了简化问题,所以我们还是讨?.4版本的代码?BR>
集合cȝҎ口Collection


Collection接口是所有集合类的根cd。它的一个主要的接口Ҏ是:

boolean add(Object c)


add()Ҏ添加一个新元素。注意这个方法会q回一个booleanQ但是返回g是表C添加成功与否。仔l阅读doc可以看到QCollection规定Q如果一个集合拒l添加这个元素,无论M原因Q都必须抛出异常。这个返回DC的意义是add()Ҏ执行后,集合的内Ҏ否改变了Q就是元素有无数量,位置{变化)Q这是由具体cd现的。即Q如果方法出错,M抛出异常Q返回g仅表CҎ执行后这个Collection的内Ҏ无变化?BR>
cM的还有:

boolean addAll(Collection c);
boolean remove(Object o);
boolean removeAll(Collection c);
boolean remainAll(Collection c);


Object[] toArray()Ҏ很简单,把集合{换成数组q回。Object[] toArray(Object[] a)Ҏ有点复杂了Q首先,q回的Object[]仍然是把集合的所有元素变成的数组Q但是类型和参数a的类型是相同的,比如执行Q?BR>
String[] o = (String[])c.toArray(new String[0]);

得到的o实际cd是String[]?BR>
其次Q如果参数a的大装不下集合的所有元素,q回的将是一个新的数l。如果参数a的大能装下集合的所有元素,则返回的q是aQ但a的内容用集合的元素来填充。尤其要注意的是Q如果a的大比集合元素的个数还多,a后面的部分全部被|ؓnull?BR>
最后一个最重要的方法是iterator()Q返回一个IteratorQP代子Q,用于遍历集合的所有元素?BR>
用Iterator模式实现遍历集合


Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合cM抽象出来Q从而避免向客户端暴露集合的内部l构?BR>
例如Q如果没有用IteratorQ遍历一个数l的Ҏ是用烦引:

for(int i=0; i<array.size(); i++) { ... get(i) ... }


而访问一个链表(LinkedListQ又必须使用while循环Q?BR>
while((e=e.next())!=null) { ... e.data() ... }

以上两种Ҏ客户端都必须事先知道集合的内部结构,讉K代码和集合本w是紧耦合Q无法将讉K逻辑从集合类和客L代码中分d来,每一U集合对应一U遍历方法,客户端代码无法复用?BR>
更恐怖的是,如果以后需要把ArrayList更换为LinkedListQ则原来的客L代码必须全部重写?BR>
决以上问题,Iterator模式L用同一U逻辑来遍历集合:

for(Iterator it = c.iterater(); it.hasNext(); ) { ... }

奥秘在于客户端自w不l护遍历集合?指针"Q所有的内部状态(如当前元素位|,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂Ҏ生成Q因此,它知道如何遍历整个集合?BR>
客户端从不直接和集合cL交道Q它L控制IteratorQ向它发?向前"Q?向后"Q?取当前元?的命令,可以间接遍历整个集合?BR>
首先看看java.util.Iterator接口的定义:

public interface Iterator {
boolean hasNext();
Object next();
void remove();
}

依赖前两个方法就能完成遍历,典型的代码如下:

for(Iterator it = c.iterator(); it.hasNext(); ) {
Object o = it.next();
// 对o的操?..
}

在JDK1.5中,q对上面的代码在语法上作了简化:

// Type是具体的cdQ如String?BR>for(Type t : c) {
// 对t的操?..
}

每一U集合类q回的Iterator具体cd可能不同QArray可能q回ArrayIteratorQSet可能q回SetIteratorQTree可能q回TreeIteratorQ但是它们都实现了Iterator接口Q因此,客户端不兛_到底是哪UIteratorQ它只需要获得这个Iterator接口卛_Q这是面向对象的威力?BR>
Iterator源码剖析


让我们来看看AbstracyList如何创徏Iterator。首先AbstractList定义了一个内部类Qinner classQ:

private class Itr implements Iterator {
...
}


而iterator()Ҏ的定义是Q?BR>
public Iterator iterator() {
return new Itr();
}

因此客户端不知道它通过Iterator it = a.iterator();所获得的Iterator的真正类型?BR>
现在我们兛_的是q个x为private的ItrcL如何实现遍历AbstractList的:

private class Itr implements Iterator {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
}

ItrcM?个int变量Q还有一个隐含的AbstractList的引用)来实现遍历,cursor是下一ơnext()调用时元素的位置Q第一ơ调用next()返回烦引ؓ0的元素。lastRet记录上一ơ游标所在位|,因此它L比cursor??BR>
变量cursor和集合的元素个数军_hasNext()Q?BR>
public boolean hasNext() {
return cursor != size();
}

Ҏnext()q回的是索引为cursor的元素,然后修改cursor和lastRet的|

public Object next() {
checkForComodification();
try {
Object next = get(cursor);
lastRet = cursor++;
return next;
} catch(IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}

expectedModCount表示期待的modCount|用来判断在遍历过E中集合是否被修改过。AbstractList包含一个modCount变量Q它的初始值是0Q当集合每被修改一ơ时Q调用addQremove{方法)QmodCount?。因此,modCount如果不变Q表C集合内Ҏ被修攏V?BR>
Itr初始化时用expectedModCount记录集合的modCount变量Q此后在必要的地方它会检modCount的|

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}

如果modCount与一开始记录在expectedModeCount中的g{,说明集合内容被修改过Q此时会抛出ConcurrentModificationException?BR>
q个ConcurrentModificationException是RuntimeExceptionQ不要在客户端捕获它。如果发生此异常Q说明程序代码的~写有问题,应该仔细查代码而不是在catch中忽略它?BR>
但是调用Iterator自n的remove()Ҏ删除当前元素是完全没有问题的Q因为在q个Ҏ中会自动同步expectedModCount和modCount的|

public void remove() {
...
AbstractList.this.remove(lastRet);
...
// 在调用了集合的remove()Ҏ之后重新讄了expectedModCountQ?BR>expectedModCount = modCount;
...
}

要确保遍历过E顺利完成,必须保证遍历q程中不更改集合的内容(Iterator的remove()Ҏ除外Q,因此Q确保遍历可靠的原则是只在一个线E中使用q个集合Q或者在多线E中寚w历代码进行同步?BR>
最后给个完整的CZQ?BR>
Collection c = new ArrayList();
c.add("abc");
c.add("xyz");
for(Iterator it = c.iterator(); it.hasNext(); ) {
String s = (String)it.next();
System.out.println(s);
}

如果你把W一行代码的ArrayList换成LinkedList或VectorQ剩下的代码不用改动一行就能编译,而且功能不变Q这是针对抽象~程的原则:对具体类的依赖性最?


早餐2? 2006-01-08 14:39 发表评论
]]>
对于javacd载器的认识(2Q?http://www.aygfsteel.com/formatmyself/articles/21330.html早餐2?早餐2?Thu, 24 Nov 2005 10:40:00 GMThttp://www.aygfsteel.com/formatmyself/articles/21330.htmlhttp://www.aygfsteel.com/formatmyself/comments/21330.htmlhttp://www.aygfsteel.com/formatmyself/articles/21330.html#Feedback0http://www.aygfsteel.com/formatmyself/comments/commentRss/21330.htmlhttp://www.aygfsteel.com/formatmyself/services/trackbacks/21330.html认识java的Classc?/A>Q另一U是׃是直接用类加蝲器ClassLoader来实现?BR>       ClassLoader一些重要的Ҏ
        A)  Ҏ loadClass
        ClassLoader.loadClass() ?ClassLoader 的入口点。该Ҏ的定义如下:
        Class loadClass( String name, boolean resolve );
        参数name  JVM 需要的cȝ名称Q如 Person ?java.lang.Object?BR>        参数 resolve 参数告诉Ҏ是否需要解析类。在准备执行cM前,应考虑c解析。ƈ不L需要解析。如?JVM 只需要知道该cL否存在或扑և该类的超c,那么׃需要解析详情见Q?A HREF="/formatmyself/articles/21291.html">认识java的Classc?/A> 中的forName()Ҏ的介l?nbsp;
        B)  Ҏ defineClass
       defineClass Ҏ?ClassLoader 的主要诀H。该Ҏ接受由原始字节组成的数组q把它{换成 Class 对象。原始数l包含如从文件系l或|络装入的数据。defineClass 理 JVM 的许多复杂、神U和倚赖于实现的斚w -- 它把字节码分析成q行时数据结构、校验有效性等{。不必担心,您无需亲自~写它。事实上Q即使您惌q么做也不能覆盖它,因ؓ它已被标记成final的?nbsp;
       C)  Ҏ findSystemClass
         findSystemClass Ҏ从本地文件系l装入文件。它在本地文件系l中LcLӞ如果存在Q就使用 defineClass 原始字节{换成 Class 对象Q以该文g转换成类。当q行 Java 应用E序Ӟq是 JVM 正常装入cȝ~省机制。(Java 2 ?ClassLoader 的变动提供了关于 Java 版本 1.2 q个q程变动的详l信息。) 对于定制?ClassLoaderQ只有在试其它Ҏ装入cM后,再?findSystemClass。原因很单:ClassLoader 是负责执行装入类的特D步骤,不是负责所有类。例如,即 ClassLoader 从远E的 Web 站点装入了某些类Q仍焉要在本地机器上装入大量的基本 Java 库。而这些类不是我们所兛_的,所以要 JVM 以缺省方式装入它们:从本地文件系l。这是 findSystemClass 的用途?nbsp;
       D) Ҏ resolveClass
       正如前面所提到的,可以不完全地Q不带解析)装入c,也可以完全地Q带解析Q装入类。当~写我们自己?loadClass Ӟ可以调用 resolveClassQ这取决?loadClass ?resolve 参数的倹{?nbsp;
      E) Ҏ findLoadedClass 
       findLoadedClass 充当一个缓存:当请?loadClass 装入cLQ它调用该方法来查看 ClassLoader 是否已装入这个类Q这样可以避免重新装入已存在cL造成的麻烦。应首先调用该方法?BR>
怎么l装q些Ҏ
  1Q?调用 findLoadedClass 来查看是否存在已装入的类?BR>  2Q?如果没有Q那么采用那U特D的奇方式来获取原始字节?BR>  3Q?如果已有原始字节Q调?defineClass 它们{换成 Class 对象?BR>  4Q?如果没有原始字节Q然后调?findSystemClass 查看是否从本地文件系l获取类?BR>  5Q?如果 resolve 参数?trueQ那么调?resolveClass 解析 Class 对象?BR>  6Q?如果q没有类Q返?ClassNotFoundException?BR>
Java 2 ?ClassLoader 的变?BR>1QloadClass 的缺省实?
   定制~写?loadClass Ҏ一般尝试几U方式来装入所h的类Q如果您~写许多c,会发Cơ次地在相同的、很复杂的方法上~写变量??Java 1.2 ?loadClass 的实现嵌入了大多数查扄的一般方法,q您通过覆盖 findClass Ҏ来定制它Q在适当的时?findClass 会调?loadClass?q种方式的好处是您可能不一定要覆盖 loadClassQ只要覆?findClass p了,q减了工作量?

2Q新ҎQfindClass
     loadClass 的缺省实现调用这个新Ҏ。findClass 的用途包含您?ClassLoader 的所有特D代码,而无需要复制其它代码(例如Q当专门的方法失败时Q调用系l?ClassLoaderQ?

3Q?新方法:getSystemClassLoader
     如果覆盖 findClass ?loadClassQgetSystemClassLoader 使您能以实际 ClassLoader 对象来访问系l?ClassLoaderQ而不是固定的?findSystemClass 调用它)?
 
4Q?新方法:getParent 
    Z类h委托l父?ClassLoaderQ这个新Ҏ允许 ClassLoader 获取它的父代 ClassLoader。当使用ҎҎQ定制的 ClassLoader 不能扑ֈcLQ可以用这U方法?BR>父代 ClassLoader 被定义成创徏?ClassLoader 所包含代码的对象的 ClassLoader?nbsp;  







早餐2? 2005-11-24 18:40 发表评论
]]>
对于javacd载器的认识(1Q?/title><link>http://www.aygfsteel.com/formatmyself/articles/21297.html</link><dc:creator>早餐2?</dc:creator><author>早餐2?</author><pubDate>Thu, 24 Nov 2005 07:53:00 GMT</pubDate><guid>http://www.aygfsteel.com/formatmyself/articles/21297.html</guid><wfw:comment>http://www.aygfsteel.com/formatmyself/comments/21297.html</wfw:comment><comments>http://www.aygfsteel.com/formatmyself/articles/21297.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/formatmyself/comments/commentRss/21297.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/formatmyself/services/trackbacks/21297.html</trackback:ping><description><![CDATA[<P>作者:早餐2? <BR>        <BR>        java是具有动态性,什么是动态性?有个最直观的例子:windowspȝ的即插即用,支持x即用的设备可以在pȝ不重新启动的情况下既可以热把插用。而java的动态性表现在Q我们的E序可以不用全盘的重新编译就能对E序某部分进行更斎ͼC#也和java一样具有动态性,而且它的q种动态性表现更为直观:直接生成windows的动态连接库文g——dll文g。而java生成的是class文gQclass是怎么实现动态性的?q个时候就全靠我们今天的主角:java的类加蝲器?BR>       我们都知道所有的javac都是承了objectq个c,在objectq个cM有一个方法:getclass(),q个Ҏq回的是一个Classcd象,具体见:<A HREF="/formatmyself/articles/21291.html">认识java的Classc?/A><BR>       一旦一个类被蝲入JVM中,同一个类׃会被再次载入了(切记Q同一个类Q。这里存在一个问题就是什么是“同一个类”?正如一个对象有一个具体的状态,x识,一个对象始l和其代?c?相关?见文<A HREF="/formatmyself/articles/21291.html">认识java的Classc?/A>)。同理,载入JVM的类也应该有一个具体的标识Q我们知道:在JAVA中,一个类用其完全匚wcd(fully qualified class name)作ؓ标识Q这里指的完全匹配类名是包名和类名。不q在JVM中一个类是用其全名再附加上一个加载类ClassLoader的实例作为唯一标识。因此,如果一个名为Pg的包中,有一个名为Cl的类Q被cd载器KlassLoader的一个实例对象kl1加蝲Q生成Cl的对象,即C1.class(q里指类Q而非对象)在JVM中表CZؓ(Cl, Pg, kl1)。这意味着两个cd载器的实?Cl, Pg, kl1) ?(Cl, Pg, kl2)是不同的Q被它们所加蝲的类也因此完全不同,互不兼容的?BR>       在java中每个类都是由某个类加蝲器的实体来蝲入的Q因此在Classcȝ实体中,都会有字D记录蝲入它的类加蝲器的实体Q当为nullӞ其实是指Bootstrap ClassLoaderQ?在javacd载器中除了引导类加蝲器(既Bootstrap ClassLoaderQ,所有的cd载器都有一个父cd载器(因ؓ他们本n自己是javac?。而类的加载机制是遵@一U委托模式:当类加蝲器有加蝲cȝ需求时Q会先请求其Parent加蝲(依次递归),如果在其父加载器树中都没有成功加载该c,则由当前cd载器加蝲?BR>        java的类加蝲器分Z下几U:<BR>        1QBootstrap ClassLoaderQ用C++实现Q一切的开始,是所有类加蝲器的最l父加蝲器。负责将一些关键的Javac,如java.lang.Object和其他一些运行时代码先加载进内存中?BR>        2QExtClassLoaderQ用java实现Q是Launcher.java的内部类Q编译后的名字ؓQLauncher$ExtClassLoader.class 。此cȝBootstrap ClassLoader加蝲Q但׃Bootstrap ClassLoader已经q了java体系(c++),所以Launcher$ExtClassLoader.class的Parent(父加载器)被设|ؓnull;它用于装载Javaq行环境扩展?jre/lib/ext)中的c,而且一旦徏立其加蝲的\径将不再改变?BR>         3QAppClassLoader,用java实现Q也是是Launcher.java的内部类Q编译后的名字ؓQLauncher$AppClassLoader.class 。AppClassLoader是当Bootstrap ClassLoader加蝲完ExtClassLoader后,再被Bootstrap ClassLoader加蝲。所以ExtClassLoader和AppClassLoader都是被Bootstrap ClassLoader加蝲Q但AppClassLoader的Parent被设|ؓExtClassLoader。可见Parent和由哪个cd载器来加载不一定是对应的?BR>个类装蝲器是我们l常使用的,可以调用ClassLoader.getSystemClassLoader() 来获得,如果E序中没有用类装蝲器相x作设定或者自定义新的c装载器Q那么我们编写的所有javac都会由它来装蝲。而它的查扑֌域就是我们常常说到的ClasspathQ一旦徏立其加蝲路径也不再改变?BR>         4QClassLoaderQ一般我们自定义的ClassLoader从ClassLoadercȝ承而来。比如:URLClassloader是ClassLoader的一个子c,而URLClassloader也是ExtClassLoader和AppClassLoader的父c(注意不是父加载器Q?BR>         <BR></P><img src ="http://www.aygfsteel.com/formatmyself/aggbug/21297.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/formatmyself/" target="_blank">早餐2?</a> 2005-11-24 15:53 <a href="http://www.aygfsteel.com/formatmyself/articles/21297.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>认识java的Classc?/title><link>http://www.aygfsteel.com/formatmyself/articles/21291.html</link><dc:creator>早餐2?</dc:creator><author>早餐2?</author><pubDate>Thu, 24 Nov 2005 07:06:00 GMT</pubDate><guid>http://www.aygfsteel.com/formatmyself/articles/21291.html</guid><wfw:comment>http://www.aygfsteel.com/formatmyself/comments/21291.html</wfw:comment><comments>http://www.aygfsteel.com/formatmyself/articles/21291.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/formatmyself/comments/commentRss/21291.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/formatmyself/services/trackbacks/21291.html</trackback:ping><description><![CDATA[        Class cL在Java语言中定义一个特定类的实现。一个类的定义包含成员变量,成员ҎQ还有这个类实现的接口,以及q个cȝ父类。Classcȝ对象用于表示当前q行?Java 应用E序中的cd接口?比如Q每个数l均属于一?Class cd象,所有具有相同元素类型和l数的数l共享一个Class 对象。基本的 Java cd(boolean, byte, char, short, int, long, float ?double) ?void cd也可表示?Class 对象?BR>以下CZ使用 Class 对象昄一个对象的 Class 名:<BR>         void printClassName(Object obj) {<BR>            System.out.println("The class of " + obj +<BR>                               " is " + obj.getClass().getName());<BR>        }<BR><BR><BR>        我们都知道所有的javac都是承了objectq个c,在objectq个cM有一个方法:getclass().q个Ҏ是用来取得该cdl被实例化了的对象的该类的引用,q个引用指向的是Classcȝ对象Q呵呵,有点别扭Q。我们自己无法生成一个Class对象Q构造函Cؓprivate)Q而这个Classcȝ对象是在当各c被调入Ӟ?Java 虚拟动创?Class 对象Q或通过c装载器中的 defineClass Ҏ生成?我们生成的对象都会有个字D记录该对象所属类在CLasscȝ对象的所在位|。如下图所C:<BR>              <IMG height=373 alt=o_1.jpg src="http://www.aygfsteel.com/images/blogjava_net/formatmyself/5215/o_1.jpg" width=436 border=0><BR>       我们可以把每个Classcȝ对象当做众多cȝ代理。而且在每个Classcd象中有会有字D记录他引用的这个类的类加蝲器。如果该字段为null,表示该类的加载器为bootstrap loader.具体原因见:<A href="/formatmyself/articles/21297.html">对于cd载器的认识一?/A>?BR><IMG height=424 alt=1.jpg src="http://www.aygfsteel.com/images/blogjava_net/formatmyself/5215/1.jpg" width=449 border=0><BR>我们知道java中有多个加蝲器,每个加蝲器能载入多个c,所以只要取得Classcd象,可利用其getClassLoader()Ҏ取得该类加蝲器的引用?BR>      jvm为每U类理者独一的Class对象。因此我们可以用双等h作符来比较对象:a1.getClass()==A.class;应该q回的是true?BR> <DT><STRONG>      forName(String classname)?forName(String classnameQboolean initialze,ClassLoader loader)   </STRONG>Ҏ<BR>      该方法返回给定串名相应的<CODE>Class</CODE> 对象。若l定一个类或接口的完整路径名,那么此方法将试图定位、装载和q接该类<FONT face=Arial>。若成功Q返回该cd象。否则,抛出 ClassNotFoundException 异常?例如Q下面代码段q回名ؓ<CODE>java.lang.Thread</CODE> 的运?<CODE>Class</CODE> 描述器?/FONT><CODE><FONT face=Arial>Class t = Class.forName("java.lang.Thread") ;  <FONT size=4><FONT size=3>此方法是需要指定类加蝲器的Q当用到仅有一个String参数的forNameҎӞClass对象默认调用当前类加蝲器作为加载器和将W二参数为true。第二个参数说明Q如果是falseӞ调用forNameҎ只是在命令类加蝲器蝲入该c,而不初始化该cȝ静态区块,只有当该cȝ一ơ实例化Ӟ静态区块才被调用。当为trueӞ则蝲入时p用静态区块?/FONT></FONT></FONT> <DT><STRONG>getClassLoader() <BR></STRONG>获取该类的类装蝲器?<BR><STRONG>getComponentType() <BR></STRONG>如果当前c表CZ个数l,则返回表C数组lg?Class 对象Q否则返?null?STRONG> <BR>getConstructor(Class[]) <BR></STRONG>q回当前 Class 对象表示的类的指定的公有构造子对象?STRONG> <BR>getConstructors() <BR></STRONG>q回当前 Class 对象表示的类的所有公有构造子对象数组?STRONG> <BR>getDeclaredConstructor(Class[]) <BR></STRONG>q回当前 Class 对象表示的类的指定已说明的一个构造子对象?<BR><STRONG>getDeclaredConstructors() <BR></STRONG>q回当前 Class 对象表示的类的所有已说明的构造子对象数组?<BR><STRONG>getDeclaredField(String) <BR></STRONG>q回当前 Class 对象表示的类或接口的指定已说明的一个域对象?STRONG> <BR>getDeclaredFields() <BR></STRONG>q回当前 Class 对象表示的类或接口的所有已说明的域对象数组?STRONG> <BR>getDeclaredMethod(String, Class[]) <BR></STRONG>q回当前 Class 对象表示的类或接口的指定已说明的一个方法对象?STRONG> <BR>getDeclaredMethods() <BR></STRONG>q回 Class 对象表示的类或接口的所有已说明的方法数l?STRONG> <BR>getField(String) <BR></STRONG>q回当前 Class 对象表示的类或接口的指定的公有成员域对象?STRONG> <BR>getFields() <BR></STRONG>q回当前 Class 对象表示的类或接口的所有可讉K的公有域对象数组?STRONG> <BR>getInterfaces() <BR></STRONG>q回当前对象表示的类或接口实现的接口<STRONG>?<BR>getMethod(String, Class[]) <BR></STRONG>q回当前 Class 对象表示的类或接口的指定的公有成员方法对象?STRONG> <BR>getMethods() <BR></STRONG>q回当前 Class 对象表示的类或接口的所有公有成员方法对象数l,包括已声明的和从父类l承的方法?STRONG> <BR>getModifiers() <BR></STRONG>q回该类或接口的 Java 语言修改器代码?STRONG> <BR>getName() <BR></STRONG>q回 Class 对象表示的类?cR接口、数l或基类?的完整\径名字符丌Ӏ?STRONG> <BR>getResource(String) <BR></STRONG>按指定名查找资源?STRONG> <BR>getResourceAsStream(String) <BR></STRONG>用给定名查找资源?STRONG> <BR>getSigners() <BR></STRONG>获取cL记?STRONG> <BR>getSuperclass() <BR></STRONG>如果此对象表C除 Object 外的Mc? 那么q回此对象的父类对象?STRONG> <BR>isArray() <BR></STRONG>如果 Class 对象表示一个数l则q回 true, 否则q回 false?STRONG> <BR>isAssignableFrom(Class) <BR></STRONG>判定 Class 对象表示的类或接口是否同参数指定?Class 表示的类或接口相同,或是其父cR?STRONG> <BR>isInstance(Object) <BR></STRONG>此方法是 Java 语言 instanceof 操作的动态等h法?STRONG> <BR>isInterface() <BR></STRONG>判定指定?Class 对象是否表示一个接口类型?STRONG> <BR>isPrimitive() <BR></STRONG>判定指定?Class 对象是否表示一?Java 的基cd<STRONG>?<BR>newInstance() <BR></STRONG>创徏cȝ新实例?STRONG> <BR>toString() <BR></STRONG>对象{换ؓ字符丌Ӏ?nbsp;<STRONG>      <BR></STRONG></CODE></DT><img src ="http://www.aygfsteel.com/formatmyself/aggbug/21291.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/formatmyself/" target="_blank">早餐2?</a> 2005-11-24 15:06 <a href="http://www.aygfsteel.com/formatmyself/articles/21291.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于jdkQjvmQjre之间的关p?/title><link>http://www.aygfsteel.com/formatmyself/articles/21247.html</link><dc:creator>早餐2?</dc:creator><author>早餐2?</author><pubDate>Thu, 24 Nov 2005 03:01:00 GMT</pubDate><guid>http://www.aygfsteel.com/formatmyself/articles/21247.html</guid><wfw:comment>http://www.aygfsteel.com/formatmyself/comments/21247.html</wfw:comment><comments>http://www.aygfsteel.com/formatmyself/articles/21247.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/formatmyself/comments/commentRss/21247.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/formatmyself/services/trackbacks/21247.html</trackback:ping><description><![CDATA[<P>作者:<A id=BlogTitleLink HREF="/formatmyself/"><FONT color=#6b86b3>早餐2?</FONT></A><BR><BR>dkQjava开发包Q包括java开发工Pjavac.exeQjar.exe{?BR>jvmQjava虚拟机。以jvm.dll文g存在于计机(windowsq_)<BR>jreQjavaq行环境?BR>        一般来_可以选择),如果安装了jdkQ计机׃存在两套jre,一套位于jdk安装目录下的/jre子目录中Q另一套位于c:\Program File\Java\下。java的程序必M靠jre才能执行Qjre包含了jvmQ也是java虚拟机。所以只要计机中正安装了jrep执行javaE序。ؓ什么jre需要安装两套了Q因为jdk中有很多的java开发工Pjdk安装目录\lib\tools.jar)本n是用java开发的Q如果要使用Q必要自行附一套jre才行Q也是jdk下面jre存在的目的(其实也可以用来执行我们的E序)Q而c:\Program File\Java\下的是用来执行我们所写的javaE序的?BR>        当我们运行java xxxӞjava.exe是按照下列顺序寻找jre的:<BR>         1Q自q录下有无jre目录<BR>         2Q父目录下的jre目录<BR>         3Q查?windows Register(HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\<BR>所以我们程序的q行与java.exe是哪个目录下和这个java.exe所指引的jre很有关系。而java.exe的指定是Ҏpȝ的path变量?BR><BR><BR><BR><BR>参考书c:《java深度历险?/P><img src ="http://www.aygfsteel.com/formatmyself/aggbug/21247.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/formatmyself/" target="_blank">早餐2?</a> 2005-11-24 11:01 <a href="http://www.aygfsteel.com/formatmyself/articles/21247.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>lLog4j配上数据库连接池http://www.aygfsteel.com/formatmyself/articles/18161.html早餐2?早餐2?Fri, 04 Nov 2005 08:24:00 GMThttp://www.aygfsteel.com/formatmyself/articles/18161.htmlhttp://www.aygfsteel.com/formatmyself/comments/18161.htmlhttp://www.aygfsteel.com/formatmyself/articles/18161.html#Feedback0http://www.aygfsteel.com/formatmyself/comments/commentRss/18161.htmlhttp://www.aygfsteel.com/formatmyself/services/trackbacks/18161.html早餐2? 

       我们都知道log4j是一个优U的开源日志记录项目,我们不仅可以对输出的日志的格式自定义Q还可以自己定义日志输出的目的地Q比如:屏幕Q文本文Ӟ数据库,甚至能通过socket输出?BR>        现在让我们对日志输出到数据库来进行配|?BR>         配置如下Q?BR>#---JDBC ---输出到数据库
# JDBCAppender log4j.properties file
#log4j.rootCategory=WARN,JDBC
# APPENDER JDBC
log4j.appender.JDBC=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.JDBC.driver=com.mysql.jdbc.Driver
log4j.appender.JDBC.URL=jdbc:mysql://localhost:3306/test
log4j.appender.JDBC.user=use
log4j.appender.JDBC.password=password
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout
log4j.appender.JDBC.sql=INSERT INTO LOGGING (log_date, log_level, location, message) VALUES ('%d{ISO8601}', '%-5p', '%C,%L', '%m')

表结构如下:
log_date   varchar2(50)
log_level  varchar2(5)
location   varchar2(100) 
message    varchar2(1000)
W者照做,但没有运行成功,而且此种Ҏ是利用传l的数据库连接方法,对于数据库的理和效率严重不I在现在这个连接池横行的时?Z么我们不能给lLog4j配上q接池,让Log4j利用数据q接池的q接和数据库q行通讯。现查看Log4j的Api,发现JDBCAppenderq个cL以下几段话:WARNING: This version of JDBCAppender is very likely to be completely replaced in the future. Moreoever, it does not log exceptions. The JDBCAppender provides for sending log events to a database.

For use as a base class:

  • Override getConnection() to pass any connection you want. Typically this is used to enable application wide connection pooling.
  • Override closeConnection(Connection con) -- if you override getConnection make sure to implement closeConnection to handle the connection you generated. Typically this would return the connection to the pool it came from.
  • Override getLogStatement(LoggingEvent event) to produce specialized or dynamic statements. The default uses the sql option value.

原来log4j我们把其提供的JDBCAppender作ؓ基类来用,然后Override三个父类的方法:getConnection(),closeConnection(Connection con)和getLogStatement(LoggingEvent event)?BR>原来如此Q那写一个子cJDBCPoolAppender来替代这个JDBCAppender
JDBCPoolAppender代码和其相关代码如下Q?BR>
JDBCPoolAppender.java:

package common.log;
import java.sql.Connection;
import org.apache.log4j.spi.LoggingEvent;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import org.apache.log4j.spi.ErrorCode;
import org.apache.log4j.PatternLayout;
import common.sql.MyDB;
import common.sql.GeneralDb;

public class JDBCPoolAppender extends org.apache.log4j.jdbc.JDBCAppender {
   
    private MyDB mydb = null;  
    protected String sqlname=""; //增加一个数据库jndiName的属?BR>    protected Connection connection = null;
    protected String sqlStatement = "";
    /**
     * size of LoggingEvent buffer before writting to the database.
     * Default is 1.
     */
    protected int bufferSize = 1;

    public JDBCPoolAppender() {
        super();
    }

    /**
     * ArrayList holding the buffer of Logging Events.
     */
    public void append(LoggingEvent event) {
        buffer.add(event);
        if (buffer.size() >= bufferSize)
            flushBuffer();
    }

    /**
     * By default getLogStatement sends the event to the required Layout object.
     * The layout will format the given pattern into a workable SQL string.
     *
     * Overriding this provides direct access to the LoggingEvent
     * when constructing the logging statement.
     *
     */
    protected String getLogStatement(LoggingEvent event) {
        return getLayout().format(event);
    }

    /**
     *
     * Override this to provide an alertnate method of getting
     * connections (such as caching).  One method to fix this is to open
     * connections at the start of flushBuffer() and close them at the
     * end.  I use a connection pool outside of JDBCAppender which is
     * accessed in an override of this method.
     * */
    protected void execute(String sql) throws SQLException {
        Connection con = null;
        Statement stmt = null;
        try {
            con = getConnection();
            stmt = con.createStatement();
            stmt.executeUpdate(sql);
        } catch (SQLException e) {
            if (stmt != null)
                stmt.close();
            throw e;
        }
        stmt.close();
        closeConnection(con);
        //System.out.println("Execute: " + sql);
    }


    /**
     * Override this to return the connection to a pool, or to clean up the
     * resource.
     *
     * The default behavior holds a single connection open until the appender
     * is closed (typically when garbage collected).
     */
    protected void closeConnection(Connection con) {
        mydb=null; 
        try {
           if (connection != null && !connection.isClosed())
               connection.close();
       } catch (SQLException e) {
           errorHandler.error("Error closing connection", e,
                              ErrorCode.GENERIC_FAILURE);
       }

    }

    /**
     * Override 此函数来利用q接池返回一个Connetion对象
     *    
     */
    protected Connection getConnection() throws SQLException { 
        try {
            mydb = GeneralDb.getInstance(sqlname);  
            connection = mydb.getConnection();     
       } catch (Exception e) {
            errorHandler.error("Error opening connection", e, ErrorCode.GENERIC_FAILURE);
        }
        return connection;
    }

    /**
     * Closes the appender, flushing the buffer first then closing the default
     * connection if it is open.
     */
    public void close() {
        flushBuffer();

        try {
            if (connection != null && !connection.isClosed())
                connection.close();
        } catch (SQLException e) {
            errorHandler.error("Error closing connection", e,
                               ErrorCode.GENERIC_FAILURE);
        }
        this.closed = true;
    }

    /**
     * loops through the buffer of LoggingEvents, gets a
     * sql string from getLogStatement() and sends it to execute().
     * Errors are sent to the errorHandler.
     *
     * If a statement fails the LoggingEvent stays in the buffer!
     */
    public void flushBuffer() {
        //Do the actual logging
        removes.ensureCapacity(buffer.size());
        for (Iterator i = buffer.iterator(); i.hasNext(); ) {
            try {
                LoggingEvent logEvent = (LoggingEvent) i.next();
                String sql = getLogStatement(logEvent);
                execute(sql);
                removes.add(logEvent);
            } catch (SQLException e) {
                errorHandler.error("Failed to excute sql", e,
                                   ErrorCode.FLUSH_FAILURE);
            }
        }

        // remove from the buffer any events that were reported
        buffer.removeAll(removes);

        // clear the buffer of reported events
        removes.clear();
    }


    /** closes the appender before disposal */
    public void finalize() {
        close();
    }


    /**
     * JDBCAppender requires a layout.
     * */
    public boolean requiresLayout() {
        return true;
    }


    /**
     *
     */
    public void setSql(String s) {
        sqlStatement = s;
        if (getLayout() == null) {
            this.setLayout(new PatternLayout(s));
        } else {
            ((PatternLayout) getLayout()).setConversionPattern(s);
        }
    }


    /**
     * Returns pre-formated statement eg: insert into LogTable (msg) values ("%m")
     */
    public String getSql() {
        return sqlStatement;
    }

    public void setSqlname(String sqlname){
        sqlname=sqlname;
    }
   
    public String getSqlname(){
        return sqlname;
    }   


    public void setBufferSize(int newBufferSize) {
        bufferSize = newBufferSize;
        buffer.ensureCapacity(bufferSize);
        removes.ensureCapacity(bufferSize);
    }

  
    public int getBufferSize() {
        return bufferSize;
    }
}


MyDB.java:
package common.sql;
import java.sql.*;
import com.codestudio.sql.*;  //引入开源项目Poolman数据库连接池的包

public class MyDB {
    public static final String module = MyDB.class.getName();
    private String dbName = "";
    private PoolMan plmn = null;


    public MyDB(String dbName) {
        try {
            if (plmn == null) {
                plmn = (PoolMan) Class.forName("com.codestudio.sql.PoolMan").
                        newInstance();
            }
        } catch (Exception ec) {
           System.out.println(ec.toString()+module);
        }
        this.dbName = dbName;
    }


    private Connection getNewConnection() {
        Connection conn = null;
        try {
            conn = plmn.connect("jdbc:poolman://" + dbName);  
            conn.setAutoCommit(true);
        } catch (Exception ec) {
            System.out.println(ec.toString()+"First:Connect sqlsever failed"+module);
            try {
                Thread.sleep(1000);
                conn = plmn.connect("jdbc:poolman://" + dbName);
                conn.setAutoCommit(true);
            } catch (Exception ecs) {
               System.out.println(ecs.toString()+"Again:Connect sqlsever faile"+module);
            }
        }
        return conn;
    }

    public Connection getConnection() {
        return getNewConnection();
    }
}
GeneralDb.java:

package common.sql;

import java.util.*;

public class GeneralDb {
    private static Hashtable dbPool;
    public static MyDB getInstance(String dbname) {
        if (dbPool == null) {
            dbPool = new Hashtable();
        }
        MyDB db = (MyDB) dbPool.get(dbname);
        if (db == null) {
            db = new MyDB(dbname);
            dbPool.put(dbname, db);
        }
        return db;
    }
}

Log4j数据库连接池的配|如下:
log4j.appender.JDBC=common.log.JDBCPoolAppender
log4j.appender.JDBC.sqlname=log
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout
log4j.appender.JDBC.sql=INSERT INTO LOGGING (log_date, log_level, location, message) VALUES ('%d{ISO8601}', '%-5p', '%C,%L', '%m')


poolman.xml配置如下Q?BR>
?xml version="1.0" encoding="UTF-8"?>
〈poolman>
  〈management-mode>local?management-mode>
  〈datasource>
    〈dbname>log?dbname>
    〈jndiName>log?jndiName>
    〈driver>com.mysql.jdbc.Driver?driver>
    〈url>jdbc:mysql://localhost:3306/test?url>
    〈username>use?username>
    〈password>password?password>
    〈minimumSize>0?minimumSize>
    〈maximumSize>10?maximumSize>
    〈logFile>logs/mysql.log?logFile>
  ?datasource>

?poolman>
   

q行成功Q对于JDBCPoolAppender的属性(比如sqlname属性)我们可以利用Log4j的反机刉便添加,只要在配|文件给光上值即可应用,而原来的父类里面的一些属性(username什么的)和其get,setҎ׃在连接池中不需要,所以删除。而在JDBCPoolAppendercMQ我也只是将getConnection ҎOverride Q在q个Ҏ中我们可以根据需要生成我们的Connection对象Q另外两个方法大家可以根据需求来军_怎样Override。:Q?BR>            


 



早餐2? 2005-11-04 16:24 发表评论
]]>
System.getProperty()参数大全 http://www.aygfsteel.com/formatmyself/articles/18017.html早餐2?早餐2?Thu, 03 Nov 2005 13:45:00 GMThttp://www.aygfsteel.com/formatmyself/articles/18017.htmlhttp://www.aygfsteel.com/formatmyself/comments/18017.htmlhttp://www.aygfsteel.com/formatmyself/articles/18017.html#Feedback0http://www.aygfsteel.com/formatmyself/comments/commentRss/18017.htmlhttp://www.aygfsteel.com/formatmyself/services/trackbacks/18017.htmlSystem.getProperty()参数大全
查资料用:
java.version Java Runtime Environment version
java.vendor Java Runtime Environment vendor
java.vendor.url Java vendor URL
java.home Java installation directory
java.vm.specification.version Java Virtual Machine specification version
java.vm.specification.vendor Java Virtual Machine specification vendor
java.vm.specification.name Java Virtual Machine specification name
java.vm.version Java Virtual Machine implementation version
java.vm.vendor Java Virtual Machine implementation vendor
java.vm.name Java Virtual Machine implementation name
java.specification.version Java Runtime Environment specification version
java.specification.vendor Java Runtime Environment specification vendor
java.specification.name Java Runtime Environment specification name
java.class.version Java class format version number
java.class.path Java class path
java.library.path List of paths to search when loading libraries
java.io.tmpdir Default temp file path

java.compiler Name of JIT compiler to use
java.ext.dirs Path of extension directory or directories
os.name Operating system name
os.arch Operating system architecture
os.version Operating system version
file.separator File separator ("/" on UNIX) path.separator Path separator (":" on UNIX)
line.separator Line separator ("\n" on UNIX)
user.name User's account name
user.home User's home directory
user.dir User's current working directory



早餐2? 2005-11-03 21:45 发表评论
]]>
Java/J2EE中文问题l极解决之道http://www.aygfsteel.com/formatmyself/articles/18016.html早餐2?早餐2?Thu, 03 Nov 2005 13:39:00 GMThttp://www.aygfsteel.com/formatmyself/articles/18016.htmlhttp://www.aygfsteel.com/formatmyself/comments/18016.htmlhttp://www.aygfsteel.com/formatmyself/articles/18016.html#Feedback0http://www.aygfsteel.com/formatmyself/comments/commentRss/18016.htmlhttp://www.aygfsteel.com/formatmyself/services/trackbacks/18016.html板桥里h http://www.jdon.com 2005/06/29

  Java中文问题一直困扰着很多初学者,如果了解了Javapȝ的中文问题原理,我们可以对中文问题能够采取Ҏ的解决之道?/P>

  最古老的解决Ҏ是用String的字节码转换Q这U方案问题是不方便,我们需要破坏对象封装性,q行字节码{换?/P>

  q有一U方式是对J2EE容器q行~码讄Q如果J2EE应用pȝq该容器,则会发生qQ而且指定容器配置不符合J2EE应用和容器分ȝ原则?/P>

  在Java内部q算中,涉及到的所有字W串都会被{化ؓUTF-8~码来进行运。那么,在被Java转化之前Q字W串是什么样的字W集Q?JavaLҎ操作pȝ的默认编码字W集来决定字W串的初始编码,而且Javapȝ的输入和输出的都是采取操作系l的默认~码?/P>

  因此Q如果能l一Javapȝ的输入、输出和操作pȝ3者的~码字符集合Q将能够使Javapȝ正确处理和显C汉字。这是处理Javapȝ汉字的一个原则,但是在实际项目中Q能够正抓住和控制住Javapȝ的输入和输出部分是比较难的。J2EE中,׃涉及到外部浏览器和数据库{,所以中文问题ؕ码显得非常突出?/P>

  J2EE应用E序是运行在J2EE容器中。在q个pȝ中,输入途径有很多种Q一U是通过面表单打包成请求(requestQ发往服务器的Q第二种是通过数据库读入;q有W?U输入比较复杂,JSP在第一ơ运行时L被编译成ServletQJSP中常常包含中文字W,那么~译使用javacӞJava根据默认的操作pȝ~码作ؓ初始~码。除非特别指定,如在Jbuilder/eclipse中可以指定默认的字符集?/P>

  输出途径也有几种Q第一U是JSP面的输出。由于JSP面已经被编译成ServletQ那么在输出Ӟ也将Ҏ操作pȝ的默认编码来选择输出~码Q除非指定输出编码方式;q有输出途径是数据库Q将字符串输出到数据库?/P>

  由此看来Q一个J2EEpȝ的输入输出是非常复杂Q而且是动态变化的Q而Java是跨q_q行的,在实际编译和q行中,都可能涉及到不同的操作系l,如果ȝJava自由Ҏ操作pȝ来决定输入输出的~码字符集,q将不可控制地出Cؕ码?/P>

  正是׃Java的跨q_Ҏ,使得字符集问题必ȝ具体pȝ来统一解决Q所以在一个Java应用pȝ中,解决中文q的根本办法是明确指定整个应用pȝl一字符集?/P>

  指定l一字符集时Q到底是指定ISO8859_1 、GBKq是UTF-8呢?

  Q?Q如l一指定为ISO8859_1Q因为目前大多数软g都是西方人编制的Q他们默认的字符集就是ISO8859_1Q包括操作系lLinux和数据库MySQL{。这P如果指定Jivel一~码为ISO8859_1Q那么就有下?个环节必L握:

  开发和~译代码时指定字W集为ISO8859_1?/P>

  q行操作pȝ的默认编码必LISO8859_1Q如Linux?/P>

  在JSP头部声明Q?lt;%@ page contentType="text/html;charset=ISO8859_1" %>?/P>

  Q?Q如果统一指定为GBK中文字符集,上述3个环节同样需要做刎ͼ不同的是只能q行在默认编码ؓGBK的操作系l,如中文Windows?/P>

  l一~码为ISO8859_1和GBK虽然带来~制代码的方便,但是各自只能在相应的操作pȝ上运行。但是也破坏了Java跨^台运行的优越性,只在一定范围内行得通。例如,Z使得GBK~码在linux上运行,讄Linux~码为GBK?/P>

  那么有没有一U除了应用系l以外不需要进行Q何附加设|的中文~码Ҏ解决Ҏ呢?

  Java/J2EEpȝ的统一~码定义为UTF-8。UTF-8~码是一U兼Ҏ有语a的编码方式,惟一比较ȝ的就是要扑ֈ应用pȝ的所有出入口Q然后用UTF-8厠Z结扎”它?/P>

  一个J2EE应用pȝ需要做下列几步工作Q?/P>

开发和~译代码时指定字W集为UTF-8。JBuilder和Eclipse都可以在目属性中讄?
使用qo器,如果所有请求都l过一个Servlet控制分配器,那么使用Servlet的filter执行语句Q将所有来自浏览器的请求(requestQ{换ؓUTF-8Q因为浏览器发过来的h包根据浏览器所在的操作pȝ~码Q可能是各种形式~码。关键一句:
request.setCharacterEncoding("UTF-8")?BR>|上有此filter的源码,Jdon框架源码中com.jdon.util.SetCharacterEncodingFilter
需要配|web.xml Ȁz该Filter?
在JSP头部声明Q?lt;%@ page contentType="text/html;charset= UTF-8" %>?
在Jsp的html代码中,声明UTF-8:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
讑֮数据库连接方式是UTF-8。例如连接MYSQL旉|URL如下Q?BR>jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8
一般数据库都可以通过理讄讑֮UTF-8
其他和外界交互时能够讑֮~码时就讑֮UTF-8Q例如读取文Ӟ操作XML{?
     W者以前在Jsp/Servlet时就采取q个原则Q后来用Struts、Tapestry、EJB、Hibernate、Jdon{框架时Q从未被q困扰q,可以说适合各种架构。希望本Ҏ供更多初学者分享,减少Java/J2EE的第一个拦路虎Q也避免因ؓ采取一些时解x案,D中文问题一直出现在新的技术架构中?
  相关J2EE中文问题解决的源码系l可参考:按这?

  Ƣ迎q入讨论 也欢q提Z外案?BR> 



早餐2? 2005-11-03 21:39 发表评论
]]>
վ֩ģ壺 Ȫ| | ͼ| Ƶ| Ȫ| ξ| | ƽ| | ٲ| | ף| | ն| ɽ| ˮ| ɣ| | | | | | | ¤| | | | ƽ| Ҧ| | | | | ʯɽ| ˫| غ| | ڽ| | | |