代理一般有静态代理,动态代理,其中静态代理是经过持有目标对象引用,而后对目标对象的方法进行加强,能够说是一种硬编码。jdk动态代理也须要持有目标对象的引用,在目标对象的方法的调用处进行加强,但这部分被封在处理器InvocationHandler中,经过反射机制生成Proxy实例,并传入处理器。----先来看下使用jdk动态代理实现方式:java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy implements InvocationHandler {
private Object target;
public DynamicProxy(Object object){
this.target = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before......");
Object result = method.invoke(target,args);
System.out.println("after......");
return result;
}
@SuppressWarnings("unchecked")
public <T> T getProxy(){
return (T)Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
}
动态是相对于静态代理而言,jvm执行java类,须要先将class文件加载到jvm中,java是不容许在运行时修改class文件的,因此要想使用动态代理,须要动态生成class文件,加载到jvm中。经过设置系统属性,能够在运行时看到jdk动态生成的class文件。spring
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");在生成的类文件中,能够看到代理类继承自Proxy并实现了业务自定义的接口,下面是动态生成的代理类部分代码:
public final class $Proxy0 extends Proxy implements IHello{能够看到jdk动态代理生成的代码,将目标对象接口的全部方法进行了代理,目标方法的执行就变成了处理器的invoke,在invoke中已经对目标对象中进行了加强。
public final String hello(String var1) throws {
return (String)super.h.invoke(this, m3, new Object[]{var1});
}
static {
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.proxy.IHello").getMethod("hello", Class.forName("java.lang.String"));
}
}
由ProxyClassFactory在给定类加载器和接口数组的条件下,生成、定义、并返回代理class。
设计模式
最后将class字节码加载到jvm,在生成代理类的函数中能够看到是否生成class文件的布尔标记saveGeneratedFiles:数组
jdk动态代理无处不在,大名鼎鼎的spring AOP默认使用的就是jdk动态代理,对于没有接口实现的类才使用cglib代理。jvm