动态代理实现有三种方式,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中不可以多继承