Java动态代理

来源:互联网 发布:延时摄影制作软件 编辑:程序博客网 时间:2024/06/05 00:52

      由于工作的原因好久没有写博客了,再次写博,目的有两,一、“烂笔头胜过最好的记忆”,所以想把自己觉得有价值的东西写下来,以便以后查阅;二、希望能遇见志同道合的朋友,将知识进行共享,讨论,使自己的技术水平有更大的提高。

     废话少说,言归正传,动态代理应该算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 来实现代理

      今天就写到这,后续会为大家进行更深入的介绍。

原创粉丝点击