-
简介
在某些场景下,我们需要增强某个对象的使用,比如我们在执行某个方法前加输出一条日志,但是我们不能直接改这个类,我们可以用代理对象来实现这个功能 -
模式应用
Spring AOP/日志/事务 等 -
类图
-
源码实现
静态代理
jdk动态代理
点击查看代码
package designpattern.proxy.jdk_proxy;
public interface SellInterface {
void sell();
}
点击查看代码
package designpattern.proxy.jdk_proxy;
public class Sell implements SellInterface {
@Override
public void sell() {
System.out.println("sell");
}
}
点击查看代码
package designpattern.proxy.jdk_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
Sell sell = new Sell();
// Proxy.newProxyInstance(Sell.class.getClassLoader(),Sell.class.getInterfaces(),);
SellInterface obj = (SellInterface)Proxy.newProxyInstance(sell.getClass().getClassLoader(), sell.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke...");
return method.invoke(sell,args);
}
});
System.out.println(obj.getClass());
obj.sell();
// System.out.println(Sell.class == sell.getClass());
while (true){
}
}
}
使用arthas工具查看动态代理类的源码
选择进程7
用sc命令查询jvm已加载的类
我们程序Client后运行输出的代理类名称是 com.sun.proxy.$Proxy0,在这个地方
用jad命令反编译,得到源码
源码如下:
点击查看代码
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* designpattern.proxy.jdk_proxy.SellInterface
*/
package com.sun.proxy;
import designpattern.proxy.jdk_proxy.SellInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0
extends Proxy
implements SellInterface {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final boolean equals(Object object) {
try {
return (Boolean)this.h.invoke(this, m1, new Object[]{object});
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
return (String)this.h.invoke(this, m2, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void sell() {
try {
this.h.invoke(this, m3, null);
return;
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
return (Integer)this.h.invoke(this, m0, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("designpattern.proxy.jdk_proxy.SellInterface").getMethod("sell", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchMethodError(noSuchMethodException.getMessage());
}
catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
}
}
稍微整理下源码,把toString hashCode equals这些方法删掉
点击查看代码
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* designpattern.proxy.jdk_proxy.SellInterface
*/
package com.sun.proxy;
import designpattern.proxy.jdk_proxy.SellInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0
extends Proxy
implements SellInterface {
private static Method m3;
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final void sell() {
this.h.invoke(this, m3, null);
return;
}
static {
m3 = Class.forName("designpattern.proxy.jdk_proxy.SellInterface").getMethod("sell", new Class[0]);
return;
}
}