版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/yjy91913/article/details/79570362
什么是代理模式?
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
动态代理与静态代理对比
静态代理实现模式
Father 是Son的代理人
Person接口
public interface Person {
void findLove();
void job();
void buy();
}
public class Son implements Person {
@Override
public void findLove() {
System.out.println("相亲");
}
@Override
public void job() {
System.out.println("干活");
}
@Override
public void buy() {
System.out.println("购物");
}
}
public class Father {
private Son son;
//静态代理缺点
//只能给儿子找对象,不能帮女儿找
public void findLove(){
System.out.println("根据你的要求物色");
this.son.findLove();
System.out.println("双方父母是否同意");
}
//静态代理,有多少方法 就得做多少代理
//在代理之前 所有东西都是已知的
public void job() {
System.out.println("根据你的要求物色");
this.son.job();
System.out.println("双方父母是否同意");
}
public void buy() {
System.out.println("根据你的要求物色");
this.son.buy();
System.out.println("双方父母是否同意");
}
}
静态代理的缺点就是 在代理之前 所有东西都是已知的 对象是固定的 方法也是固定的
JDK动态代理实现模式
/**
* 原理
* 1.拿到被代理对象的引用,并且获取其接口通过反射获取
* 2.通过JDK的Proxy类,重新生成新的类,同时实现被代理类所实现的所有接口
* 3.动态的生成java代码,在Proxy把新加的业务逻辑方法,去调用(在代码中体现)
* 4.编译新生成的java代码.class
* 5.再重新加载JVM运行
*
* 以上就叫字节码重组
* JDK有规范 只要是$开头一般都是自动生成
*
* 通过反编译可以查看源代码
*/
先写一个Demo
先写一个代理类,他是一个媒婆 代理了Man (Man实现了Person接口
public class JDKMeiPo implements InvocationHandler{
private Person target;
public Object getInstance(Person target){
this.target = target;
Class clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("findLove".equalsIgnoreCase(method.getName())){
System.out.println("我是媒婆,我要给你找对象");
Object invoke = method.invoke(this.target, args);
System.out.println("如果合适就准备办事");
return invoke;
}else {
Object invoke = method.invoke(this.target, args);
return invoke;
}
}
}
这个就是测试类,可以这是 我们的person已经是一个被代理过后的增强类
public class JDKProxyTest {
public static void main(String[] args) throws IOException {
Person person = (Person) new JDKMeiPo().getInstance(new Man());
person.findLove();
System.out.println(person.getClass());
//从JVM拿到临时生成的解码文件,把这个字节码文件储存起来
byte[] $proxy0s = ProxyGenerator.generateProxyClass("$proxy0", new Class[]{person.getClass()});
FileOutputStream os = new FileOutputStream("E:\\$proxy0.class");
os.write($proxy0s);
}
}
这个文件我们可以通过反编译,内容如下:
这个就是JDK生成的字节码文件:
import com.sun.proxy..Proxy0;
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 Proxy0 {
private static Method m1;
private static Method m5;
private static Method m3;
private static Method m2;
private static Method m6;
private static Method m11;
private static Method m13;
private static Method m0;
private static Method m8;
private static Method m12;
private static Method m7;
private static Method m10;
private static Method m4;
private static Method m9;
public $proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final InvocationHandler getInvocationHandler(Object var1) throws IllegalArgumentException {
try {
return (InvocationHandler)super.h.invoke(this, m5, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void findLove() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 Class getProxyClass(ClassLoader var1, Class[] var2) throws IllegalArgumentException {
try {
return (Class)super.h.invoke(this, m6, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final Class getClass() throws {
try {
return (Class)super.h.invoke(this, m11, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void notifyAll() throws {
try {
super.h.invoke(this, m13, (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)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void wait() throws InterruptedException {
try {
super.h.invoke(this, m8, (Object[])null);
} catch (RuntimeException | InterruptedException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void notify() throws {
try {
super.h.invoke(this, m12, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final Object newProxyInstance(ClassLoader var1, Class[] var2, InvocationHandler var3) throws IllegalArgumentException {
try {
return (Object)super.h.invoke(this, m7, new Object[]{var1, var2, var3});
} catch (RuntimeException | Error var5) {
throw var5;
} catch (Throwable var6) {
throw new UndeclaredThrowableException(var6);
}
}
public final void wait(long var1) throws InterruptedException {
try {
super.h.invoke(this, m10, new Object[]{Long.valueOf(var1)});
} catch (RuntimeException | InterruptedException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final boolean isProxyClass(Class var1) throws {
try {
return ((Boolean)super.h.invoke(this, m4, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void wait(long var1, int var3) throws InterruptedException {
try {
super.h.invoke(this, m9, new Object[]{Long.valueOf(var1), Integer.valueOf(var3)});
} catch (RuntimeException | InterruptedException | Error var5) {
throw var5;
} catch (Throwable var6) {
throw new UndeclaredThrowableException(var6);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m5 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getInvocationHandler", new Class[]{Class.forName("java.lang.Object")});
m3 = Class.forName("com.sun.proxy.$Proxy0").getMethod("findLove", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m6 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getProxyClass", new Class[]{Class.forName("java.lang.ClassLoader"), Class.forName("[Ljava.lang.Class;")});
m11 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getClass", new Class[0]);
m13 = Class.forName("com.sun.proxy.$Proxy0").getMethod("notifyAll", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m8 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", new Class[0]);
m12 = Class.forName("com.sun.proxy.$Proxy0").getMethod("notify", new Class[0]);
m7 = Class.forName("com.sun.proxy.$Proxy0").getMethod("newProxyInstance", new Class[]{Class.forName("java.lang.ClassLoader"), Class.forName("[Ljava.lang.Class;"), Class.forName("java.lang.reflect.InvocationHandler")});
m10 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", new Class[]{Long.TYPE});
m4 = Class.forName("com.sun.proxy.$Proxy0").getMethod("isProxyClass", new Class[]{Class.forName("java.lang.Class")});
m9 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", new Class[]{Long.TYPE, Integer.TYPE});
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
以上代码可以得出这个新的临时的类是按照我们需求加强的