动态代理实现的三种方式

动态代理实现有三种方式,jdk动态代理(基于接口),cglib动态代理(基于继承),javassist(hibernate中使用这种方式)实现动态代理

一 jdk实现动态代理

package com.lzzl.jdkproxy;

public interface Pet {
    public void say();
}


package com.lzzl.jdkproxy;

public class Dog implements Pet{
    public void say(){
        System.out.println("wang wang wang !");
    }
}



package com.lzzl.jdkproxy;

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

public class ProxyFactory implements InvocationHandler{
    private Object target;

    public Object getTarget() {
        return target;
    }
    public void setTarget(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result;
        if(proxy instanceof Pet){
             if("say".equals(method.getName())){
                 System.out.println(" say 前");
                 result = method.invoke(target, args);
                 System.out.println(" say 后");
                 return result;
             }

        }
        return method.invoke(target, args);
    }
    public Object createProxy(){
        Class[] interfaces = target.getClass().getInterfaces();
        if(interfaces.length==0){
            System.out.println("该类无接口,不能使用jdk都动态代理");
            throw new RuntimeException("该类无接口,不能使用jdk都动态代理");
        }
        return Proxy.newProxyInstance(ProxyFactory.class.getClassLoader(), interfaces, this);
    }
}

测试下

package com.lzzl.jdkproxy;

import java.io.FileOutputStream;
import java.io.OutputStream;

import sun.misc.ProxyGenerator;

public class runjdkproxytest {
        public static void main(String[] args) throws Exception{
            Dog dog = new Dog();
            ProxyFactory proxyfc = new ProxyFactory();
            proxyfc.setTarget(dog);
            Pet proxy = (Pet) proxyfc.createProxy();
            proxy.say();
            //这里用于生成代理类的字节码文件
            byte[] bts = ProxyGenerator.generateProxyClass("DogProxy", new Class[]{Pet.class});
            OutputStream out = new FileOutputStream("E:\\work\\myeclipsework\\DynamicProxy\\generateFile\\DogProxy.class");
            out.write(bts);
        }
}

输出:
say 前
wang wang wang !
say 后

生成的字节码文件反编译后

import com.lzzl.jdkproxy.Pet;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class DogProxy extends Proxy
  implements Pet
{
  private static Method m3;
  private static Method m1;
  private static Method m0;
  private static Method m2;

  public DogProxy(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  public final void say()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  static
  {
    try
    {
      m3 = Class.forName("com.lzzl.jdkproxy.Pet").getMethod("say", new Class[0]);
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

可以看出来生成的代理类是继承了Proxy类,这也是jdk动态代理只能基于接口而不能基于继承实现动态代理的原因了,因为java中不可以多继承

你可能感兴趣的:(java-笔记)