这个和反射不同的地方在于,这个东西有接口

这里话进行学习的话得需要四个java代码

image-20230315183517863

一个接口和其他三个class

这里的IUser是一个接口

image-20230315190938799

UserImpl是一个继承于IUser接口,里面重写了IUser接口里的show()方法

image-20230315190955845

UserProxy也是一个继承IUser接口,里面也是重写了show方法

image-20230315191007234

ProxyTest是个产生代理对象的类

image-20230315191016626

在这个产生代理对象的类里边进行操作

image-20230315190818909

这里因为UserImpl类是继承了IUser接口,所以这里的类型得定义为IUser.

然后这里就会调用UserImpl类里边的show方法

image-20230315191145326

接下来使用另一个类

image-20230315191304912

image-20230315191339554

这里是会输出两个展示,因为UserProxy里面有一个有参构造函数,传的值是别人传入的对象,因为这里传入的对象是UserImpl的,所以在UserProxy调用show方法时,就会调用到UserImpl类里边的show方法

以上展示的就是静态代理了

动态代理

这里出现的动态代理就是因为静态代理有缺点,因为如果接口里面有很多函数的话,日志(UserImpl)里面也要重写很多函数的方法,代理类(UserProxy)里边也要重写很多类的方法。就会比较繁琐

这里要实现动态代理的话,就是得想要这个方法

image-20230315193449922

image-20230315193502567

这个方法限定了三个参数,前两个都是写死的,只要是最后一个,这个是关键(就是把想要做的东西传进去)

1
Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(),xxx);

这个xxx就是我们要做的事情

所以我们得先新建一个类

image-20230315204047548

image-20230315204109374

然后对这个invoke进行重写

image-20230315204538812

这里和前面的那个代理类差不多,但是这里用的InvocationHandler这个类,

这个invoke函数,只要我们能传进来东西,他就会知道我们调用的是哪个方法,这是这个函数的性质

我们就到代理测试类那边进行调试

1
2
InvocationHandler invocationHandler = new UserinvocationHandler(user);
IUser user1 = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(),invocationHandler);

我们就是利用这个invocationHandler这个类来进行动态代理,所以在new一个对象的时候,我们就用它。

然后再把实例化后的对象放进下面的Proxy.newProxyInstance里;

image-20230315205413275

然后就可以直接调用这个方法了

image-20230315205707219

在这个类里边新加这个方法的话,就可以直接调用了了,就不用再去代理类里边重写函数的方法了,这样的话就大大减少了代码量

1
IUser user1 = (IUser) Proxy.newProxyInstance(iUser.getClass().getClassLoader(), iUser.getClass().getInterfaces(),invocationHandler);

这里的代码也可以写成这样

1
IUser user1 = (IUser) Proxy.newProxyInstance(iUser.getClass().getClassLoader(), new Class[]{IUser.class},invocationHandler);

image-20230315210106913

跟这个有关