java反序列化JDK动态代理
Sherlock静态代理
首先定义一个接口,实现类,以及一个代理类
1 2 3 4 5
| package com.sherlock;
public interface IUser { void show(); }
|
1 2 3 4 5 6 7 8 9 10 11 12
| package com.sherlock;
public class UserImpl implements IUser{ public UserImpl(){
}
@Override public void show() { System.out.println("展示"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| package com.sherlock;
public class UserProxy implements IUser { IUser user; public UserProxy(){} public UserProxy(IUser user) {this.user = user;} @Override public void show() { user.show(); System.out.println("调用了show"); } }
|
下面我们就来测试一下
1 2 3 4 5 6 7 8 9 10
| package com.sherlock;
public class ProxyTest { public static void main(String[] args) { IUser user = new UserImpl(); IUser userProxy = new UserProxy(user); userProxy.show(); } }
|
静态代理其实就相当于起到了日志记录的功能,比如上述例子中打印调用了show这句话不可能在实现类中出现,只能够在代理类中输出
但是静态代理有一个劣势,就是接口有时候所需要的实现方法不止一个,然后即使是进行重复性的方法代理(如同样加入一个记录日志的功能),也需要在代理类中把方法一个一个都实现了,过于繁琐,那么要怎么解决呢
JDK底层为我们提供了一个解决方案,那就是动态代理
动态代理
一个重要的方法,用于代理一个对象:
我们跟进方法,参数需要一个类加载器对象,一个接口数组对象以及一个InvocationHandler对象;返回的是Object对象
对于InvocationHandler
对象,重写一下该invoke方法,此处的invoke()方法就是在于解决静态代理中需要重复重写方法的缺陷,动态代理的好处就是能获取到外部调用的那个方法,然后通过反射来到内部来执行被代理对象的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package com.sherlock;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;
public class UserInvocationHandler implements InvocationHandler { IUser user; public UserInvocationHandler(){};
public UserInvocationHandler(IUser user) { this.user = user; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用了"+method.getName()); method.invoke(user, args); return null; } }
|
InvocationHandler中的invoke方法当外面有调用方法的时候都会自动执行
然后我们简单测试一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.sherlock;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy;
public class ProxyTest { public static void main(String[] args) { IUser user = new UserImpl(); InvocationHandler userinvocationhandler = new UserInvocationHandler(user); IUser userProxy = (IUser)Proxy.newProxyInstance(user.getClass().getClassLoader(),user.getClass().getInterfaces(),userinvocationhandler); userProxy.update(); } }
|
其实newProxyInstance的第二个参数是获取到一个接口数组,所以我们也可以写成下面这种方式
1 2 3
| IUser userProxy = (IUser)Proxy.newProxyInstance(user.getClass().getClassLoader(), new Class[]{IUser.class}, userinvocationhandler);
|