??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲色大成网站www永久一区,亚洲国产高清美女在线观看,亚洲人成网站在线播放影院在线http://www.tkk7.com/dyerac/dyerac In Javazh-cnSun, 11 May 2025 11:24:35 GMTSun, 11 May 2025 11:24:35 GMT60Openfire, spark, red5http://www.tkk7.com/dyerac/archive/2007/09/29/149692.htmldyerac in java...dyerac in java...Sat, 29 Sep 2007 14:06:00 GMThttp://www.tkk7.com/dyerac/archive/2007/09/29/149692.htmlhttp://www.tkk7.com/dyerac/comments/149692.htmlhttp://www.tkk7.com/dyerac/archive/2007/09/29/149692.html#Feedback2http://www.tkk7.com/dyerac/comments/commentRss/149692.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/149692.htmlOpenfireQ原来的WildfireQ是一个跨q_Q采用Java开发,开源的实时协作QRTCQ服务器ZXMPPQJabberQ协议。Openfire安装和用都非常单,q利用Webq行理。单台服务器可支持上万ƈ发用?br />
Spark是Openfire的客LQ?br />
Red5是基于java的flash媒体服务器

 

以后有兴就研究一下子?/p>

dyerac in java... 2007-09-29 22:06 发表评论
]]>
手动创徏一个新Classhttp://www.tkk7.com/dyerac/archive/2007/08/13/136473.htmldyerac in java...dyerac in java...Mon, 13 Aug 2007 10:52:00 GMThttp://www.tkk7.com/dyerac/archive/2007/08/13/136473.htmlhttp://www.tkk7.com/dyerac/comments/136473.htmlhttp://www.tkk7.com/dyerac/archive/2007/08/13/136473.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/136473.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/136473.html
public class NewMain {
    public static void main(String[] args) {
        new Object();
    }
}

用javap反编译上面的代码Q我们可以得C面的指oQ这里省Mjavac暗中创徏的构造函数?br>
public class NewMain extends java.lang.Object{
    ...
public static void main(java.lang.String[]);
  Code:
   0:   new     #3; //class java/lang/Object
   3:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   6:   return
}

从这D代码中Q我们可以清晰的看出创徏对象QnewQ和调用构造函敎ͼinvokespecialQ两个过E。关于这个问题,我在?a target=_blank>对象的生?/font>》中曄q行q讨论?br>
既然javac一个new的动作被解释Z条指令,那在JVM的层面上Q我们当然就可以它们分开。下面是一D|什么实际用途的代码Q只是证明这个观点可行性?br>
public class NewGenerator {
    public static void main(String[] args) throws Exception {
        String className = "New";
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        cw.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
        Method m = Method.getMethod("void main (String[])");
        GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, m, null, null, cw);
        mg.newInstance(Type.getType(Object.class));
        Label label = mg.newLabel();
        mg.ifNonNull(label);
        mg.mark(label);
        mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
        mg.push("new object is not null");
        mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println(java.lang.String)"));
        mg.pop();
        mg.returnValue();
        mg.endMethod();
        cw.visitEnd();

        OutputStream os = null;
        try {
            os = new FileOutputStream(className + ".class");
            os.write(cw.toByteArray());
        } finally {
            if (os != null) {
                os.close();
            }
        }
    }
}

q段代码生成的类是能够运行的Q有兴趣的可以自p一下。这D代码的作用是newZ个对象之后,如果q个对象非空的话Q就会生一个输出:
    new object is not null

当然Q如果尝试用q个对象做一些其它的操作Q会有错误等待着我们Q因个对象ƈ不是一个完整的对象。在JVM规范中有相关的解释:new指oq不能完整创建出一个新的对象,直到Ҏ初始化的对象调用了实例初始化Ҏ才会完成实例的创建。这D代码也正好W合?a target=_blank>对象的生?/font>》中的解释,它只是负责做出申请内存。当Ӟ在JVM中,它的实际工作要略多一些,如果q个对象的类没有加蝲Q就会加载相应的cR?br>

]]>
Google Ajax Search api 以及 web api 的设计和架构?http://www.tkk7.com/dyerac/archive/2007/07/25/132362.htmldyerac in java...dyerac in java...Wed, 25 Jul 2007 09:52:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/25/132362.htmlhttp://www.tkk7.com/dyerac/comments/132362.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/25/132362.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/132362.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/132362.html题记:
其实我这文章纯_Ҏ抛砖引玉之意
Google Ajax Search 的api使用hq不困难,如果有高手对此不屑一儡?不妨回答一下我的真正用?那就是一个出色的web api该如何设计呢? 它的体系架构是什? 我对此有个初步的x, 前端开发自qjs? 调用q端的服? 但是具体实施该如何呢? 传输方式该是如何? JSON? 自定义XML? q是SOAP? 现在很火的REST?web api的设计有什么媄? q望各位高手赐教 ^_^

回到正题,看看如何用google api构徏自己的ajax 搜烦.  阅读全文

]]>
动态代?Dynamic ProxyQJava Servlet http://www.tkk7.com/dyerac/archive/2007/07/24/132051.htmldyerac in java...dyerac in java...Tue, 24 Jul 2007 07:10:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/24/132051.htmlhttp://www.tkk7.com/dyerac/comments/132051.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/24/132051.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/132051.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/132051.html基本上了解了动态代理的机制
差写个代码实验一?br>

------------------------------------------------------------------------------------------------------------------------


从JDK1.3开始,Java引入了动态代理的概念。动态代理(Dynamic ProxyQ可以帮助你减少代码行数Q真正提高代码的可复用度。例如,你不必ؓ所有的cȝҎ里面都写上相同的Log代码行,取而代之的是实用类的动态代理类。当Ӟq种便利是有条g的。本文简单介lJava动态代理的原理Qƈ实现一个被代理的Servlet创徏Q和调用的过E?
 
1Q?/span>代理模式QProxy PatternQ?/div>
在JDK1.3以前Q代理模式就已流行,所以得代理模式是生成一个和cȝ同接口的代理c,用户通过使用代理cL装某个实现cR如?Q其目的是加强实现类的某个方法的功能Q而不必改变原有的源代码?/div>

2Q?/span>动态代理(Dynamic ProxyQ?/div>
随着Proxy的流行,Sun把它U_到JDK1.3实现了Java的动态代理。动态代理和普通的代理模式的区别,是动态代理中的代理类是由java.lang.reflect.Proxycdq行期时Ҏ接口定义Q采用Java反射功能动态生成的。和java.lang.reflect.InvocationHandlerl合Q可以加强现有类的方法实现。如?Q图中的自定义Handler实现InvocationHandler接口Q自定义Handler实例化时Q将实现cM入自定义Handler对象。自定义Handler需要实现invokeҎQ该Ҏ可以使用Java反射调用实现cȝ实现的方法,同时当然可以实现其他功能Q例如在调用实现cL法前后加入Log。而ProxycL据Handler和需要代理的接口动态生成一个接口实现类的对象。当用户调用q个动态生成的实现cLQ实际上是调用了自定义Handler的invokeҎ?/div>
  

3Q动态代理Servlet
              虽然Web Application Server的品很多,但Servlet的处理原理是怼的:动态加载ServletQ调用Servlet的initҎQ只被调用一ơ)Qƈ保存到Servlet容器QServlet使用Ӟ调用Servlet的serviceҎ。本文动态代理Servlet接口Q其init和service被调用时会在控制台打出方法调用前后信息?/div>
首先实现2个ServletQDefaultServlet和UserServlet
 
package org.colimas.servlet;
 
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
 
public class DefaultServlet extends HttpServlet implements Servlet {
              public void init() throws ServletException {
                            super.init();
                            System.out.println(DefaultServlet.class.getName()+":Running init");
              }
 
              public String getServletInfo() {
                            return DefaultServlet.class.getName();
              }
}
 
package org.colimas.servlet;
 
import java.io.IOException;
 
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
public class UserServlet extends HttpServlet implements Servlet {
 
              private static final long serialVersionUID = -7016554795165038652L;
             
              public void init() throws ServletException {
                            super.init();
                            System.out.println(UserServlet.class.getName()+":Running init");
              }
              protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                                         
                            System.out.println(UserServlet.class.getName()+":Do UserSErvlet Get");
              }
              public String getServletInfo() {
                            return UserServlet.class.getName();
              }            
             
 
}
 
然后实现InvocationHandler
package org.colimas.webapp;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
import javax.servlet.Servlet;
 
public class ServletHandler implements InvocationHandler {
 
              private Servlet obj;
             
              public ServletHandler(Servlet obj){
                            this.obj=obj;
              }
              public Object invoke(Object arg0, Method arg1, Object[] arg2)
                                          throws Throwable {
                           
                            if(arg1.getName().compareTo("init")==0) //调用init?/div>
                            {
                                          System.out.println(obj.getServletInfo()+":Init servlet starting..."); //增加控制台输出?/div>
                                          arg1.invoke(obj,arg2); //调用initҎ
                                          System.out.println(obj.getServletInfo()+":Init servlet ending..."); //增加控制台输出?/div>
                            }else if(arg1.getName().compareTo("service")==0){ //调用service?/div>
                                          System.out.println(obj.getServletInfo()+":service starting..."); //增加控制台输出?/div>
 
                                          arg1.invoke(obj,arg2); //调用serviceҎ?/div>
                                          System.out.println(obj.getServletInfo()+":service ending..."); //增加控制台输出?/div>
                           
                            }
                            return null;
              }
 
}
 
实现Servlet的调?/div>
package org.colimas.webapp;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
 
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
 
public class ServletWrapperImp {
   
    private Class servletClass;
    private ServletConfig config;
    private String _servletname;
    private Servlet _theServlet;
              private ServletContext context;
    public ServletWrapperImp(ServletConfig config){
           this.config=config;
           this._servletname=this.config.getServletName();
           this.context=this.config.getServletContext();
    }
   
    public Servlet getServlet() throws ServletException{
 
                              destroy();
                              try {
                                            WebAppClassLoader loader=new WebAppClassLoader(this.getClass().getClassLoader()); //自定义class loader
                                            String name=getServletName(); //从ServletConfig中获得Servlet Name
                                            synchronized (context) {
                                                          Servlet theServlet=context.getServlet(name); //在ServletContext中查找Servlet
                                                          if(theServlet==null){         //如果ServletContext没有?span>              
                                                                        servletClass = loader.loadClass(name); //由Class loader 加蝲Servlet class?/div>
                                                              theServlet = (Servlet) servletClass.newInstance(); //Servlet实例化?/div>
                                                              WebAppContext.addServlet(name,theServlet); //Servlet实例存入ServletContext?/div>
                                                                        InvocationHandler handler=new ServletHandler(theServlet); //自定义ServletHandlerQ参见ServletHandlercR?/div>
                                                                        _theServlet=(Servlet)Proxy.newProxyInstance(theServlet.getClass().getClassLoader(),
                                                                                   new Class[]{Servlet.class},handler); //代理cd例化?/div>
                                                                        _theServlet.init(config); //Servlet代理对象调用initҎ。参见ServletHandler的invokeҎ?/div>
                                                                       
                                                          }else{ //ServletContext里已存在?/div>
                                                                        InvocationHandler handler=new ServletHandler(theServlet); //自定义ServletHandlerQ参见ServletHandlercR?/div>
                                                                        _theServlet=(Servlet)Proxy.newProxyInstance(theServlet.getClass().getClassLoader(),
                                                                                   new Class[]{Servlet.class},handler);                 //代理Servlet接口Q动态生成代理类Qƈ实例化?span>                                  
                                                          }
                                            }
                                            return _theServlet; //q回Servlet代理对象
                              } catch( ClassNotFoundException ex1 ) {
                                
                              } catch( InstantiationException ex ) {
                                 
                              }catch(IllegalAccessException ex2){
                                           
                              }
                      return null;
    }
    public void destroy() {
        if (_theServlet != null) {
                      _theServlet.destroy();
        }
    }   
   
    protected String getServletName(){
           return _servletname;
    }
}
 
其中的ServletConfig保存Servlet相关信息。ServletContext保存所有的Servlet对象。WebAppClassLoader定义class loader,参见http://blog.csdn.net/tyrone1979/archive/2006/09/03/1164262.aspx?/div>
 
最后编写测试类MainQ该cL?0个用戯问ServletQ?问DefaultServletQ?问UserServlet?/div>
package org.colimas.main;
 
import java.io.IOException;
 
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
 
import org.colimas.webapp.HttpServletRequestWrapper;
import org.colimas.webapp.HttpServletResponseWrapper;
import org.colimas.webapp.ServletConfigImpl;
import org.colimas.webapp.ServletWrapper;
import org.colimas.webapp.ServletWrapperImp;
import org.colimas.webapp.WebAppContext;
 
public class Main {
 
              private ThreadGroup _threadGroup;
              private Thread[] _threads;
              String defaultServletName="org.colimas.servlet.DefaultServlet";
              String userServletName="org.colimas.servlet.UserServlet";
              WebAppContext context=WebAppContext.newInstance();     
             
              public void doStart(){
             
                            _threadGroup=new ThreadGroup("SERVLETS");
                            int i=0;
                            _threads=new ServletThread[10]; //模拟10位用戗?/div>
                            for(i=0;i<5;i++){
                                          _threads[i]=new ServletThread(_threadGroup,new Integer(i).toString(),
                                                                      defaultServletName);
                                          _threads[i].start();
                            }
                            for(i=5;i<10;i++){
                                          _threads[i]=new ServletThread(_threadGroup,new Integer(i).toString(),
                                                                      userServletName);
                                          _threads[i].start();
                            }                          
                           
              }
              /**
               * @param args
               */
              public static void main(String[] args) {
                            Main _main=new Main();
                            _main.doStart();
                           
              }
              //模拟用户U程
              private class ServletThread extends Thread{
                           
                            private String servletName;
                           
                            public ServletThread(ThreadGroup group,String threadname,String servletname){
                                          super(group,threadname);
                                          servletName=servletname;
                            }
                            //调用Servlet的service.
                            public void run() { //用户调用Servlet
                                          ServletConfig config=new ServletConfigImpl(servletName,context); //调用的Servlet信息?/div>
                                          ServletWrapperImp wrapper=new ServletWrapperImp(config);
                                          try {
                                                        Servlet defaultServlet=wrapper.getServlet(); //获得Servlet对象Q实际是Servlet的代理对?/div>
                                                        defaultServlet.service(new HttpServletRequestWrapper(),
                                                                                    new HttpServletResponseWrapper()); 调用代理对象的serviceҎQ参见ServletHandler的invokeҎ?/div>
                                          } catch (ServletException e) {
                                                                                                                e.printStackTrace();
                                          } catch(IOException e){
                                                       
                                          }
                            }
                           
              }
}
HttpServletRequestWrapper和HttpServletResponseWrapper实现HttpServletRequestQ和HttpServletResponse?/div>
试l果如下
org.colimas.servlet.DefaultServlet:Init servlet starting...
org.colimas.servlet.DefaultServlet:Running init
org.colimas.servlet.DefaultServlet:Init servlet ending...
org.colimas.servlet.UserServlet:Init servlet starting...
org.colimas.servlet.UserServlet:Running init
org.colimas.servlet.UserServlet:Init servlet ending...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service ending...
 
2个ServletW一ơLoad时初始化Q被调用initQ之后保存到ServletContext中。第二次直接从ServletContext获得Q执行service。红字表CZ理类里增加的输出l果?/div>
 
4Q动态代理的限制
              JDK的动态代理ƈ不能随心所Ʋ的代理所有的cRProxy.newProxyInstanceҎ的第二个参数只能是接口数l, 也就是Proxy只能代理接口?/div>

 



]]>动态代?包装器模?/title><link>http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html</link><dc:creator>dyerac in java...</dc:creator><author>dyerac in java...</author><pubDate>Tue, 24 Jul 2007 06:03:00 GMT</pubDate><guid>http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html</guid><wfw:comment>http://www.tkk7.com/dyerac/comments/132037.html</wfw:comment><comments>http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/dyerac/comments/commentRss/132037.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dyerac/services/trackbacks/132037.html</trackback:ping><description><![CDATA[<p>转的q篇文章虽然是讲动态代理的<br>但是其中涉及CDecorator模式 也是一个学习的亮点<br><br><br><br><br>-----------------------------------------------------------------------------------------------------<br>记忆是衍生自Lisp,Python,和Perl{过E性语a的一U设计模式,它可以对前次的计结果进行记忆?nbsp;一个实C记忆功能的函? 带有昑ּ的cache, 所? 已经计算q的l果p直接从cache中获? 而不用每ơ都q行计算.<br>记忆能显著的提升大计量代码的效? 而且是一U可重用的方?<br>本文阐述了在Java中用这一模式的方?q提供了一个可以提供上q功能的"记忆c?:<br>     Foo foo = (Foo) Memoizer.memoize(new FooImpl());<br>     q里,Foo是一个接?它含有的Ҏ是需要记忆的.FooImpl是Foo的一个实?foo是Foo的一个引?Ҏ与FooImpl基本相同,区别在于Fooq回的?会被~存h.单个记忆cȝ优点在于ZQ何类d记忆功能是很单的:定义一个包含需要记忆的Ҏ的接?然后调用memoize来实C个实?<br><br>    Z理解记忆cL怎么实现?我们分几步来解?首先,我解释一下ؓ何缓存能够在需要它的类中实?然后,我测试一下如何ؓ一个特定的cL加缓存包装器.最?我解释一下如何才能得一个缓存包装器能够通用于Q意的c?<br><br><strong>为大计算量的E序d~存</strong><br>    作ؓ一个大计算量程序的例子,我们考虑PiBinaryDigitsCalculatorq个例子-计算二进制数据pi.仅有的publicҎcalculateBinaryDigit带有一个参?整数n,代表需要精到的位?例如,1000000,会q回数点后的一百万?通过byteD?每位?或?.(法可以参? <a target=_blank><font color=#002c99><u>http://www.cecm.sfu.ca/~pborwein/PAPERS/P123.pdf</u></font></a>)<br><br><code>public class PiBinaryDigitsCalculator {<br>  /**<br>   * Returns the coefficient of 2^n in the binary<br>   * expansion of pi.<br>   * @param n the binary digit of pi to calculate.<br>   * @throws ValidityCheckFailedException if the validity<br>   * check fails, this means the implementation is buggy<br>   * or n is too large for sufficient precision to be<br>   * retained.<br>   */<br>  public byte calculateBinaryDigit(final int n) {<br>      return runBBPAlgorithm(n);<br>  }<br>    <br>  private byte runBBPAlgorithm(final int n) {<br>      // Lengthy routine goes here ...<br>  }<br><br>}</code><br>    最单直接的Ҏ来缓存返回值可以通过修改q个cL实现:d一个Map来保存之前计得到的?如下:<br><code>import java.util.HashMap;<br><br>public class PiBinaryDigitsCalculator {<br><br>  private HashMap cache = new HashMap();<br><br>  public synchronized byte calculateBinaryDigit(<br>  final int n) {<br><br>      final Integer N = new Integer(n);<br>      Byte B = (Byte) cache.get(N);<br>      if (B == null) {<br>          byte b = runBBPAlgorithm(n);<br>          cache.put(N, new Byte(b));<br>          return b;<br>      } else {<br>          return B.bytevalue();<br>      }<br>  }<br><br>  private byte runBBPAlgorithm(final int n) {<br>      // Lengthy routine goes here ...<br>  }<br>}</code><br> <br>    calculateBinaryDigitҎ首先会检查HashMap里面是否~存了这个关键字-参数n,如果扑ֈ?q接返回这个?否则,׃q行q个冗长的计?q将l果保存到缓存里?在添加进HashMap的时?在原始类型和对象之间q要q行小的{?<br>    管q个Ҏ是可行的,但是有几个缺?首先,q行~存的代码和正常的算法代码不是显著分开?一个类,不仅负责q行计算,也要负责q行l护~存数据.q样,要进行一些测试就会显得很困难.比如,不能写一个测试程序来试q个法持箋地返回相同的?因ؓ,从第二次开?l果都是直接从cache中获得了.<br>    其次,当缓存代码不再需?U除它会变得困难,因ؓ它和法块地代码是紧密结合在一L.所?要想知道~存是否带来了很高的效率提升也是很困隄,因ؓ不能写一个测试程序是和缓存数据分开?当你改进了你的算?~存有可能失?但是q个时候你q不知道.<br>    W三,~存代码不能被重?管代码遵从了一个普通的模式,但是都是在一个类- PiBinaryDigitsCalculator里面.<br><br>    前面两个问题都可以通过构造一个缓存包装器来解?<br><br><strong style="COLOR: #993366">~存包装?/strong><br>    通过使用Decorator模式,要分开计算代码和缓存代码是很容易的.首先,定义一个接?里面定义基本的方?<br>     <code>public interface BinaryDigitsCalculator {<br><br>  public byte calculateBinaryDigit(final int n);<br>}</code><br>    <br><br>    <span style="COLOR: #ff0000">然后定义两个实现,分别负责两个d:</span><br><code>public class PiBinaryDigitsCalculator<br>  implements BinaryDigitsCalculator {<br><br>  public byte calculateBinaryDigit(final int n) {<br>      return runBBPAlgorithm(n);<br>  }<br><br>  private byte runBBPAlgorithm(final int n) {<br>      // Lengthy routine goes here ...<br>  }<br><br>}<br><br>import java.util.HashMap;<br><br>public class CachingBinaryDigitsCalculator implements<br>BinaryDigitsCalculator {<br><br>  private BinaryDigitsCalculator binaryDigitsCalculator;<br>  private HashMap cache = new HashMap();<br><br>  public CachingBinaryDigitsCalculator(<br>  BinaryDigitsCalculator calculator) {<br>      this.binaryDigitsCalculator = calculator;<br>  }<br><br>  public synchronized byte calculateBinaryDigit(int n) {<br>      final Integer N = new Integer(n);<br>      Byte B = (Byte) cache.get(N);<br>      if (B == null) {<br>          byte b =<br>            binaryDigitsCalculator.calculateBinaryDigit(n);<br>          cache.put(N, new Byte(b));<br>          return b;<br>      } else {<br>          return B.bytevalue();<br>      }<br>  }<br>}</code><br>    <br>    q是很之前的实现PiBinaryDigitsCalculator的一U简单的refactored版本. CachingBinaryDigitsCalculator包装了BinaryDigitsCalculator句柄,q增加了~存,供calculateBinaryDigit的方法调? q种Ҏ提高了代码的可读性与可维护? 用户不能直接使用BinaryDigitsCalculator接口来实现算?所?如果需要关闭缓存块,是很容易实现的.<br>    q有,合适的试E序很容易写出来.比如,我们写一个假的BinaryDigitsCalculator实现,每次calculateBinaryDigit被调?赋予相同的参?q回不同的? q样,我们p试~存是否工作?因ؓ如果每次都返回相同的?则证明缓存是正常工作? q种试在之前U简单的实现是不可能?<br><br>q是很之前的实现PiBinaryDigitsCalculator的一U简单的refactored版本. CachingBinaryDigitsCalculator包装了BinaryDigitsCalculator句柄,q增加了~存,供calculateBinaryDigit的方法调? q种Ҏ提高了代码的可读性与可维护? 用户不能直接使用BinaryDigitsCalculator接口来实现算?所?如果需要关闭缓存块,是很容易实现的.<br><br>    q有,合适的试E序很容易写出来.比如,我们写一个假的BinaryDigitsCalculator实现,每次calculateBinaryDigit被调?赋予相同的参?q回不同的? q样,我们p试~存是否工作?因ؓ如果每次都返回相同的?则证明缓存是正常工作? q种试在之前U简单的实现是不可能的?br>通过动态代理类来创Z个通用的缓存包装器\r<br><br>    上面W二U方法仅有的~点是~存包装器不能重?每次我们希望d一个缓存给某个c?我们p写一个特D的~存包装器给目标接口.q是一个很?Ҏ出错的过E?<br><br>    Jdk1.3开始支持动态代理类: 特别的类能够在运行期军_实现哪个接口-通常的模式都?在运行期卛_定实现哪个接?通过q个,我们有可能实C个通用的缓存包装器,我们U它为Memoizer,在运行期军_实现哪个接口.q样, CachingBinaryDigitsCalculator是不再需要的.它是q样被调用的:<br><br>BinaryDigitsCalculator calculator =<br>new CachingBinaryDigitsCalculator(<br>new PiBinaryDigitsCalculator()<br>);  <br><br>    可以通过Memoizer来重写如?<br><br>BinaryDigitsCalculator calculator =<br>(BinaryDigitsCalculator) Memoizer.memoize(<br>new PiBinaryDigitsCalculator()<br>);<br><br>Memoizer的代码如?<br></p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000"> demo.proxy;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.InvocationHandler;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.InvocationTargetException;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.Method;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.Proxy;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Arrays;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Collections;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.HashMap;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.List;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Map;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_361_1538_Open_Image onclick="this.style.display='none'; Codehighlighter1_361_1538_Open_Text.style.display='none'; Codehighlighter1_361_1538_Closed_Image.style.display='inline'; Codehighlighter1_361_1538_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_361_1538_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_361_1538_Closed_Text.style.display='none'; Codehighlighter1_361_1538_Open_Image.style.display='inline'; Codehighlighter1_361_1538_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Memorizer </span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000"> InvocationHandler </span><span id=Codehighlighter1_361_1538_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_361_1538_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_409_543_Open_Image onclick="this.style.display='none'; Codehighlighter1_409_543_Open_Text.style.display='none'; Codehighlighter1_409_543_Closed_Image.style.display='inline'; Codehighlighter1_409_543_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_409_543_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_409_543_Closed_Text.style.display='none'; Codehighlighter1_409_543_Open_Image.style.display='inline'; Codehighlighter1_409_543_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Object memorize(Object object) </span><span id=Codehighlighter1_409_543_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_409_543_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> Proxy.newProxyInstance(object.getClass().getClassLoader(),<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>                object.getClass().getInterfaces(), </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Memorizer(object));<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Object object;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Map caches </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap();<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_643_670_Open_Image onclick="this.style.display='none'; Codehighlighter1_643_670_Open_Text.style.display='none'; Codehighlighter1_643_670_Closed_Image.style.display='inline'; Codehighlighter1_643_670_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_643_670_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_643_670_Closed_Text.style.display='none'; Codehighlighter1_643_670_Open_Image.style.display='inline'; Codehighlighter1_643_670_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Memorizer(Object object) </span><span id=Codehighlighter1_643_670_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_643_670_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.object </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> object;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Object invoke(Object proxy, Method method, Object[] args)<br><img id=Codehighlighter1_759_1125_Open_Image onclick="this.style.display='none'; Codehighlighter1_759_1125_Open_Text.style.display='none'; Codehighlighter1_759_1125_Closed_Image.style.display='inline'; Codehighlighter1_759_1125_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_759_1125_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_759_1125_Closed_Text.style.display='none'; Codehighlighter1_759_1125_Open_Image.style.display='inline'; Codehighlighter1_759_1125_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>            </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Throwable </span><span id=Codehighlighter1_759_1125_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_759_1125_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Don't cache void methods</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_839_875_Open_Image onclick="this.style.display='none'; Codehighlighter1_839_875_Open_Text.style.display='none'; Codehighlighter1_839_875_Closed_Image.style.display='inline'; Codehighlighter1_839_875_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_839_875_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_839_875_Closed_Text.style.display='none'; Codehighlighter1_839_875_Open_Image.style.display='inline'; Codehighlighter1_839_875_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (method.getReturnType().equals(Void.TYPE)) </span><span id=Codehighlighter1_839_875_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_839_875_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> invoke(method, args);<br><img id=Codehighlighter1_882_1122_Open_Image onclick="this.style.display='none'; Codehighlighter1_882_1122_Open_Text.style.display='none'; Codehighlighter1_882_1122_Closed_Image.style.display='inline'; Codehighlighter1_882_1122_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_882_1122_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_882_1122_Closed_Text.style.display='none'; Codehighlighter1_882_1122_Open_Image.style.display='inline'; Codehighlighter1_882_1122_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span id=Codehighlighter1_882_1122_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_882_1122_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            Map cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> getCache(method);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            List key </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Arrays.asList(args);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            Object value </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> cache.get(key);<br><img id=Codehighlighter1_1035_1101_Open_Image onclick="this.style.display='none'; Codehighlighter1_1035_1101_Open_Text.style.display='none'; Codehighlighter1_1035_1101_Closed_Image.style.display='inline'; Codehighlighter1_1035_1101_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1035_1101_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1035_1101_Closed_Text.style.display='none'; Codehighlighter1_1035_1101_Open_Image.style.display='inline'; Codehighlighter1_1035_1101_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (value </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">cache.containsKey(key)) </span><span id=Codehighlighter1_1035_1101_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1035_1101_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>                value </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> invoke(method, args);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>                cache.put(key, value);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>            }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> value;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>        }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1198_1327_Open_Image onclick="this.style.display='none'; Codehighlighter1_1198_1327_Open_Text.style.display='none'; Codehighlighter1_1198_1327_Closed_Image.style.display='inline'; Codehighlighter1_1198_1327_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1198_1327_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1198_1327_Closed_Text.style.display='none'; Codehighlighter1_1198_1327_Open_Image.style.display='inline'; Codehighlighter1_1198_1327_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Object invoke(Method method, Object[] args) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Throwable </span><span id=Codehighlighter1_1198_1327_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1198_1327_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_1206_1249_Open_Image onclick="this.style.display='none'; Codehighlighter1_1206_1249_Open_Text.style.display='none'; Codehighlighter1_1206_1249_Closed_Image.style.display='inline'; Codehighlighter1_1206_1249_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1206_1249_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1206_1249_Closed_Text.style.display='none'; Codehighlighter1_1206_1249_Open_Image.style.display='inline'; Codehighlighter1_1206_1249_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> </span><span id=Codehighlighter1_1206_1249_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1206_1249_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> method.invoke(object, args);<br><img id=Codehighlighter1_1287_1324_Open_Image onclick="this.style.display='none'; Codehighlighter1_1287_1324_Open_Text.style.display='none'; Codehighlighter1_1287_1324_Closed_Image.style.display='inline'; Codehighlighter1_1287_1324_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1287_1324_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1287_1324_Closed_Text.style.display='none'; Codehighlighter1_1287_1324_Open_Image.style.display='inline'; Codehighlighter1_1287_1324_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (InvocationTargetException e) </span><span id=Codehighlighter1_1287_1324_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1287_1324_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000"> e.getTargetException();<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>        }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1375_1536_Open_Image onclick="this.style.display='none'; Codehighlighter1_1375_1536_Open_Text.style.display='none'; Codehighlighter1_1375_1536_Closed_Image.style.display='inline'; Codehighlighter1_1375_1536_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1375_1536_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1375_1536_Closed_Text.style.display='none'; Codehighlighter1_1375_1536_Open_Image.style.display='inline'; Codehighlighter1_1375_1536_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">synchronized</span><span style="COLOR: #000000"> Map getCache(Method m) </span><span id=Codehighlighter1_1375_1536_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1375_1536_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        Map cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (Map) caches.get(m);<br><img id=Codehighlighter1_1433_1517_Open_Image onclick="this.style.display='none'; Codehighlighter1_1433_1517_Open_Text.style.display='none'; Codehighlighter1_1433_1517_Closed_Image.style.display='inline'; Codehighlighter1_1433_1517_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1433_1517_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1433_1517_Closed_Text.style.display='none'; Codehighlighter1_1433_1517_Open_Image.style.display='inline'; Codehighlighter1_1433_1517_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (cache </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">) </span><span id=Codehighlighter1_1433_1517_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1433_1517_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Collections.synchronizedMap(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap());<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            caches.put(m, cache);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>        }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> cache;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"> </span></div> <p><br><br>当调用静态方法memoize的时?会创徏一个新的代理实?也就是一个java.lang.reflect.proxy的实?实现了一个接口集.q个接口集由object.getClass().getInterfaces()来决?每个代理实例包含一个java.lang.reflect.InvocationHandler实例来处理这个代理实例调用的相关Ҏ.在我们的例子?Memoizer是一个InvocationHandler实例.</p> <p>    当一个方法在代理实例里被调用,比如, calculateBinaryDigit,那么, Memoizer实例里的invokeҎ׃被调?相关信息会传linvokeҎ,以决定proxy实例调用了哪个方?包含参数信息.在我们的例子?传入Memoizer的java.lang.Method参数是calculateBinaryDigit,而参C息则是pi需要精的位数-整数n.在这个基?Memoizer能够q一步进行缓存操作的.</p> <p>    在例子里(caches是一个Hashmap,cache是一个map)里用到的Key,主要是传入的Ҏ信息:Method对象和参数对? Z实现的简单与通用?Memoizer有一个关于cache的HashMap caches,每个method是一个key,对应的valueZ个cache.然后把参C息{化成一个List对象,作ؓcache的Key.使用List是很方便?同时也可以保证equals()Ҏ,所以能够保证当且仅当参C息完全相同的时候这个List才相{?</p> <p>    一旦一个cache的Key被创?那么,计算之前都会先查找这个cache,如果扑ֈ,则返回cache里的?否则,如果带有q些参数的这个方法没有被调用q?那么,则会通过invoke来调用这个method.在我们的例子? 实例PiBinaryDigitsCalculator 里的calculateBinaryDigitҎ会通过invoke被调?而且计算l果会被存在cache?<br>何时使用Memoizer</p> <p>    作ؓ一条通用的规?Memoizer能够在Q何需要传l的cache的时候?比如上面提到的例? 特别?接口里每个需要用记忆功能的method需要满下面几条条?</p> <p>    1. q个method的返回值最好不要每ơ调用都会改变\r</p> <p>    2. q个method不要有副效应</p> <p>    3. q个method的参数是定?非mutable?</p> <p>    昄,如果每次调用q个methodq回值都不同,那么cache毫无用处了.同样也是很重要的一Ҏ,因ؓ有副效应的method不会被重?所以这个method不能有副效应(method自动更新某些状?.当然,voidҎ除外.</p> <p>    同样,memorize一个带有未?mutable)参数的method是很危险?因ؓ,要把q些参数储存到hashmap里会是很危险的一件事.ҎMap的定?当这个Map里的key发生改变,Map是不知道?所?当你执行了一ơ这个method之后,相关信息dq了Map,然后参数发生变异(mutate),W二ơ调用的时?׃得到错误的结?</p> <p>    性能</p> <p>    使用cache的主要目的就是ؓ了提升你的程序的速度.然?reflection是众所周知的低?在jdk1.4里有所改进,通过reflection调用Ҏ是普通调用速度?/2,q个比jdk1.3要快40?.Memoizer主要依靠reflection来调用方?所?它看上去q不是一个好的途径.但是,如果使用cache能给E序速度带来的提升远高于reflection寚w度的媄?那么,使用Memoizer是值得考虑?</p> <p>    在我们对PiBinaryDigitsCalculator的测试中,试环境为jdk1.4,当n于10的时?使不使用cache速度是相当的.但是,当n增大的时?使用cache的优势就开始显C出?所?l常使用PiBinaryDigitsCalculator的用?可以考虑使用cache.</p> <p>    不幸的是,唯一试你的E序是否需要cache的途径是比较你的程序在两种情况下的q行效率.管如此,因ؓZ个程序构造一个cache包装器是很容易的一件事,U除它也是很Ҏ?下面的徏议可以作Z个参考的步骤:</p> <p>    1. 选择需要记忆操作的c\r</p> <p>    2. q行它\r</p> <p>    3. 如果效率是满意的,go to 6</p> <p>    4. dmemoizer,使用cache</p> <p>    5. 如果效率没有显著提升,Udmemoizer</p> <p>    6. 如果需?重试.</p> <p>    理论?你需要分析ؓ一个类d记忆功能Ҏ个系l的影响.只有你自己清楚是否值得d.有些Ҏ,即是计量很大?但是在这个系l里很少被调?所?没必要ؓ它添加记忆功?Z保证q个,我开发了一个更有特点的Memoizer,实现了一个叫做CacheStatistics的接?你能从它得到cache的数量以及无效的cache.你可以用它作ؓ判断的一个尺?</p> <p>    扩展Memoizer</p> <p>    修改MemoizercL支持不同的cache{略是很单的.一个比较普通的cd是Least-Recently-Used(LRU)cahce,拥有固定数量的入?q个cache保入口不大于它的最大数?如果过,摒弃最旧的~存数据.也就?能够从cache里得到的是新的数?一个类可以使用LRU cache来防止一个程序长期保持一个状?你可以仅仅传递一个参数给CacheFactory里的memoizeҎ来选择你需要的cachecd.下面的例?LRU cache最多有1000个入?</p> <p>BinaryDigitsCalculator calculator =<br>(BinaryDigitsCalculator) Memoizer.memoize(<br>new PiBinaryDigitsCalculator(),<br>new LruCacheFactory(1000)<br>); </p> <p>    即是这么简?Memoizer也应该是javaE序员一个有用的工具.</p> <img src ="http://www.tkk7.com/dyerac/aggbug/132037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dyerac/" target="_blank">dyerac in java...</a> 2007-07-24 14:03 <a href="http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML,RPC,RMI,SOAP,WSDL,RESR,Web Services Relationshttp://www.tkk7.com/dyerac/archive/2007/07/24/132004.htmldyerac in java...dyerac in java...Tue, 24 Jul 2007 03:10:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/24/132004.htmlhttp://www.tkk7.com/dyerac/comments/132004.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/24/132004.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/132004.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/132004.htmlRMI   is   object   based   protocal   which   you   can   serialize   your   object   and   make   a   remote   call   on   object   thru   it.

XMLRPC   is   message   (XML)   based   and   you   can   not   use   object   at   all.   The   advantage   is   security   and   reliability.   With   XML   you   can   encrypt   and   validate   any   way   you   like.   SOAP   is   XMLRPC   on   HTTP   by   XML   message



]]>
定义自己的热?/title><link>http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html</link><dc:creator>dyerac in java...</dc:creator><author>dyerac in java...</author><pubDate>Tue, 24 Jul 2007 03:06:00 GMT</pubDate><guid>http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html</guid><wfw:comment>http://www.tkk7.com/dyerac/comments/132002.html</wfw:comment><comments>http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/dyerac/comments/commentRss/132002.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dyerac/services/trackbacks/132002.html</trackback:ping><description><![CDATA[<p>* 一个用KeyStroke自定义快捷键的示?br> * <br>*/<br>public class MnemonicT extends JFrame {<br> private int count = 0;</p> <p> private JButton button;</p> <p> public MnemonicT() {<br>  super("Mnemonic Test");<br>  JPanel panel = new JPanel();<br>  panel.setPreferredSize(new Dimension(320, 240));<br>  panel.setLayout(new FlowLayout());</p> <p>  button = new JButton(new AbstractAction("ClickTimes:" + count) {<br>   public void actionPerformed(ActionEvent e) {<br>    button.setText("ClickTimes:" + (++count));<br>   }<br>  });<br>  panel.add(button);<br>  add(panel);</p> <p>  InputMap im = button.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW);<br>  im.put(KeyStroke.getKeyStroke("control A"), "buttonAction"); // 按CTRL+A<br>  button.getActionMap().put("buttonAction", button.getAction());<br>  pack();<br>  setDefaultCloseOperation(EXIT_ON_CLOSE);<br> }</p> <p> public static void main(String[] args) {<br>  SwingUtilities.invokeLater(new Runnable() {<br>   public void run() {<br>    new MnemonicT().setVisible(true);<br>   }<br>  });<br> }<br>}</p> <img src ="http://www.tkk7.com/dyerac/aggbug/132002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dyerac/" target="_blank">dyerac in java...</a> 2007-07-24 11:06 <a href="http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QztQannotation relationshttp://www.tkk7.com/dyerac/archive/2007/07/22/131760.htmldyerac in java...dyerac in java...Sun, 22 Jul 2007 14:42:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/22/131760.htmlhttp://www.tkk7.com/dyerac/comments/131760.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/22/131760.html#Feedback1http://www.tkk7.com/dyerac/comments/commentRss/131760.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/131760.html阅读全文

]]>
学习计划http://www.tkk7.com/dyerac/archive/2007/07/19/131329.htmldyerac in java...dyerac in java...Thu, 19 Jul 2007 09:57:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/19/131329.htmlhttp://www.tkk7.com/dyerac/comments/131329.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/19/131329.html#Feedback2http://www.tkk7.com/dyerac/comments/commentRss/131329.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/131329.html    现在开始学习啦Q列个小的计划吧:
    论文阅读计划QRESTQ?Blueprint 4 mashupQ?J2EE Clustering
    框架学习计划QApache CXFQ?Dom4JQ?DB4OQAspectJ
    基础学习计划QXML
    语言学习计划QJavascriptQPython
   
   重点学习计划QAjaxQRESTQWeb Services


Zȝ下这几天看的几个名词Q?br>
RESTQ?br>AtomQ?br>FeedQ?br>SOAPQ?br>WSDLQ?br>JSONQ?br>MashupQ?

]]>
Editplus配置http://www.tkk7.com/dyerac/archive/2007/07/17/130884.htmldyerac in java...dyerac in java...Tue, 17 Jul 2007 08:48:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/17/130884.htmlhttp://www.tkk7.com/dyerac/comments/130884.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/17/130884.html#Feedback1http://www.tkk7.com/dyerac/comments/commentRss/130884.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/130884.html1. 以sqlZQ需要sql.stx(语法)  sql.acpQauto completementQ放到editplus目录下即?br>2. 另外修改settings.ini{几个ini文gQ主要是针对acp文gQ?br>3. q启动editplus用tool工具导入stx文g q设|高亮染色方案(alertQ我只发C导入 没找到手工修改的?nbsp;
    法)
4. 创徏template.sql文g q修改template.ini 注意 也要修改ini中显C的模板数目Q而非仅仅dQ?br>5. that's all

]]>
վ֩ģ壺 99ֻоƷƵѿ| ѹƵվ| avһ| һѹۿ| ŷһ| ۺ| þþþþAVվ| ޾Ʒ˳߲| ޹Ʒ˰| һëƬëƬһëƬ| ˳վ߹ۿ| 㽶AVվ߹ۿ| ޻ɫ߹ۿ| ڵaëƬѿ| ޾ƷŮɫ| ŷëƬAƵ޷| ˾Ʒѿ| պƷһ| ޾þþþþ| AëƬ| aëƬƵѹۿӰԺ| ŷͽȺ| avһ| պƷƵһ | ڵƵ| baoyu777Ƶ| ޾ƷGVͬ| ձһ߶ | ɫվַ| һƵ| AVרAV| ޹ۺ| A޾VƷ | ˳Ƶx8x8| պϵ | AVպƷþþþþ| պ޹| Ļվ| AVһ| ëƬڵ| ؼaa**ëƬѹۿ|