Java動態代理<一>

由於工作的原因好久沒有寫博客了,再次寫博,目的有兩,一、“爛筆頭勝過最好的記憶”,所以想把自己覺得有價值的東西寫下來,以便以後查閱;二、希望能遇見志同道合的朋友,將知識進行共享,討論,使自己的技術水平有更大的提高。

廢話少說,言歸正傳,動態代理應該算java的核心技術,Spring的AOP的底層實現用了,hibernate的接口實現也用了,由此可見動態代理至於java確實非常重要,那麼今天就來討論一下動態代理。java中的動態代理大家接觸最多的應該是:JDK 的動態代理和CGLIB動態代理。我將從以下幾個方面討論這個問題:

1、兩者區別

2、詳細介紹JDK動態代理

3、詳細介紹CGLIB動態代理

4、兩者的性能對比

首先討論區別:

還是以程序員習慣的代碼出發進行討論:

1.JDK的動態代理

接口:

public interface Helloworld {


String say(String name);//在這裏我還是用大家熟悉的helloworld作爲演示示例
}


接口實現類:


public class HelloworldImp implements Helloworld{

@Override
public String say(String name) {
return "hello:"+name;
}
}


代理實例的調用處理程序 實現的接口



import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;





public class HelloworldHandler implements InvocationHandler {
private Object methodProxy;


public HelloworldHandler(Object methodProxy) {
this.methodProxy = methodProxy;//需要代理的對象,在這個例子中就是helloWorldImp
}


@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result;
System.out.println("Before Helloworld");
result=method.invoke(methodProxy, args);//執行代理對象的方法
System.out.println("After HelloWorld");
return result;
}

}





測試代碼:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Date;







public class TestJdk {

/**
* @param args
*/
public static void main(String[] args) {

HelloworldImp helloWorldImp=new HelloworldImp();
InvocationHandler invocationHandler=new HelloworldHandler(helloWorldImp);
Helloworld helloWorld=(Helloworld) Proxy.newProxyInstance(helloWorldImp.getClass().getClassLoader(),helloWorldImp.getClass().getInterfaces(),invocationHandler);
Date startDate=new Date();
helloWorld.say("柯磊");
Date endDate=new Date();
System.out.println("用時:"+(endDate.getTime()-startDate.getTime()));
}

}

2.CGLIB動態代理

爲了更好的對比兩者,在這裏使用一樣的HelloworldImp,但是提醒一下,Helloworld接口不是必須的。
public class HelloworldImp implements Helloworld{

@Override
public String say(String name) {
// TODO Auto-generated method stub
return "hello:"+name;
}
}


代理類:

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


public class HelloworldProxy implements MethodInterceptor {

@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object result;
System.out.println("Before Helloworld");
result=methodProxy.invokeSuper(obj, args);
System.out.println("After HelloWorld");
return result;
}

}

測試代碼:

import javax.xml.crypto.Data;

import net.sf.cglib.proxy.Enhancer;


public class TestCglib {

/**
* @param args
*/
public static void main(String[] args) {
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(HelloworldImp.class);
enhancer.setCallback(new HelloworldProxy());
HelloworldImp helloWorld=(HelloworldImp) enhancer.create();
Date startDate=new Date();
helloWorld.say("柯磊");
Date endDate=new Date();
System.out.println("用時:"+(endDate.getTime()-startDate.getTime()));
}

}



通過上面的代碼我們能很清楚看出二者的區別:

1、JDK 的動態代理只能對實現了接口的目標類進行代理,而不實現接口的類就不能使用 JDK 的動態代理

2、CGLIB 是針對類來實現代理,當沒有實現接口的類需要代理時,也可以通過 CGLIB 來實現代理

今天就寫到這,後續會爲大家進行更深入的介紹。


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/kehongyong/archive/2010/11/30/6046438.aspx
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章