静态代理
首先定义一个接口,实现类,以及一个代理类
| 12
 3
 4
 5
 
 | package com.sherlock;
 public interface IUser {
 void show();
 }
 
 | 
| 12
 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("展示");
 }
 }
 
 | 
| 12
 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");
 }
 }
 
 | 
下面我们就来测试一下
| 12
 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()方法就是在于解决静态代理中需要重复重写方法的缺陷,动态代理的好处就是能获取到外部调用的那个方法,然后通过反射来到内部来执行被代理对象的方法
| 12
 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方法当外面有调用方法的时候都会自动执行
然后我们简单测试一下
| 12
 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的第二个参数是获取到一个接口数组,所以我们也可以写成下面这种方式
| 12
 3
 
 | IUser userProxy = (IUser)Proxy.newProxyInstance(user.getClass().getClassLoader(),new Class[]{IUser.class},
 userinvocationhandler);
 
 |