我们首先编写一个接口IUser

1
2
3
4
public interface IUser {  
void show();
void update();
}

再写一个类来实现这个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class UserImpl implements IUser {  
public UserImpl(){

}

@Override
public void show(){
System.out.println("show~");
}

@Override
public void update(){
System.out.println("update~");
}
}

我们再编写一个动态代理类UserInvocationHandler,并覆写它的invoke方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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; }
}

为了方便对比,我们再编写一个静态代理UserProxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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_IN_PROXY");
}

@Override
public void update(){
user.update();
System.out.println("UPDATE_IN_PROXY");
}
}

我们首先使用静态代理来调用静态代理中的方法

1
2
3
4
5
6
7
8
9
10
public class ProxyTest {  
public static void main(String[] args){
IUser user = new UserImpl();
user.show();
//静态代理
IUser userProxy = new UserProxy(user);
userProxy.show();

}
}

image.png
如果对这里为什么有两个show有疑问,请好好看代码
那么如果我们想要向接口中增加方法,我们不仅需要增加接口中,更需要在接口的实现类中覆写,那么如果我们用动态代理类,只需要去更新接口就可以了,这样在后期维护的时候会省很多事
我们尝试用如下的代码来测试动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Proxy;

public class ProxyTest {
public static void main(String[] args){
IUser user = new UserImpl();
// user.show();
// //静态代理
// IUser userProxy = new UserProxy(user);
// userProxy.show();
//如果接口中方法增多,对应的代理中的override方法也要增多,所以静态代理在接口变化后实现的相当繁琐

// 动态代理
// 参数:接口,要做的事情,classloader
InvocationHandler userinvocationhandler = new UserInvocationHandler(user);
IUser userproxy = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(),user.getClass().getInterfaces(),userinvocationhandler);// public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)InvocationHandler:调用处理器
userproxy.update();
}
}

image.png
根据输出结果我们可以轻易的发现动态代理对象每执行一个方法的时候都被转发到InvocationHandler的接口类的invoke方法来调用