代理是种设计模式,对目标方法的访问转移到代理对象上。
jdk动态代理
jdk的动态代理由Proxy这个类来生成,它有三个参数
- ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的
- Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型
- InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入.
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
}
public interface InvocationHandler {
void invoke(Object proxy, Method method, Object[] args);
}
proxy => 这个参数指定动态生成的代理类,这里是TimeProxy
method => 这个参数表示传入接口中的所有Method对象
args => 这个参数对应当前method方法中的参数
下面是一个简单的例子说明:
目标接口
public interface Subject {
void request();
}
目标实现类:
public class SubjectImpl implements Subject{
@Override
public void request() {
System.out.println("##reuqdt");
}
}
InvocationHandler实现类:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target){
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法执行前处理");
Object result = method.invoke(target,args);
System.out.println("方法执行前后处理");
return result;
}
}
Subject target = new SubjectImpl();
Subject subjectProxy=(Subject)Proxy.newProxyInstance(Client.class.getClassLoader(),new Class[]{Subject.class},new MyInvocationHandler (target));
subjectProxy.request();
// 执行过程:subjectProxy.request() => handler.invoke()
在动态生成的代理类的任意方法中都会间接调用InvocationHandler->invoke(proxy, method, args)方法。简单总结:
- Proxy.newProxyInstance生成代理对象
- InvocationHandler 接口用于自定义代理逻辑。
- 未来完成被代理对象的方法拦截,需要在InvocationHandler实现类中传入被代理对象的实例。
方法调用过程:
最好我们来看下生成的代理对象class,调用以下方法:
public static void createProxyClassFile()
{
String name = "ProxySubject";
byte[] data = ProxyGenerator.generateProxyClass( name, new Class[] { Subject.class } );
try
{
FileOutputStream out = new FileOutputStream( name + ".class" );
out.write( data );
out.close();
}
catch( Exception e )
{
e.printStackTrace();
}
}
生成类如下:
public final class ProxySubject extends Proxy implements Subject {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public ProxySubject(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void request() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
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.staticproxy.Subject").getMethod("request");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}