本文共 4052 字,大约阅读时间需要 13 分钟。
什么是代理?
代理是一种设计模式。通过代理对象间接的反问被代理对象。(是的就是这么简单)怎么理解呢?
举个例子: 小明*(被代理对象)*去详情了,想约女孩出来看电影(代理事务),但是不想自己去找女孩,这时候找到媒婆(代理对象)去传话,达到约会的目的。 我们通过上图想一想,代理的好处和作用。通过上述生动的讲述,是不是很容易理解了什么是代理了?为什么需要代理了?下面通过代码层面彻底分析和了解下代理。
Java代理分为静态代理和动态代理
两者有什么区别呢?我们先介绍完,再去分析(介绍完就很容易理解了)。通过上面的了解我们可以知道,想要实现代理是不是得满足几个条件:
有了几点我们开始代码层面实现静态代理:
public interface SayToWatchTv { public void sayToWatchTv();}被代理对象小明:跟小美说去看电影。/** * 代理对象-- 小明 on 2021/3/23. */public class NoProxyClass implements SayToWatchTv{ public void sayToWatchTv() { System.out.println("小美我们去看电影吧"); }}代理对象媒婆,需要继承和小明一样的接口,且实现代理事物,但是最终还是调用的小明对象的实现方法/** * Created by on 2021/3/23. * 代理对象媒婆 */public class ProxyClass implements SayToWatchTv{ NoProxyClass noProxyClass = new NoProxyClass(); // 初始化被代理对象 public void sayToWatchTv() { noProxyClass.sayToWatchTv(); // 最终还是调用了被代理对象的方法 }}public class MainClass { public static void main(String[] args) { ProxyClass proxyClass =new ProxyClass(); proxyClass.sayToWatchTv(); }}
结果:
看到这是不是感觉静态代理tm也太简单了吧,神经病吧,为啥我不直接调用被代理对象的方法哦。还绕这个弯路。
那现在对照着代理的优点我们分析下:/** * Created by on 2021/3/23. * 代理对象媒婆 */public class ProxyClass implements SayToWatchTv{ NoProxyClass noProxyClass = new NoProxyClass(); public void sayToWatchTv() { System.out.println("小明去理了发"); noProxyClass.sayToWatchTv(); }}2. 很容易看出来,main方法里面直接调用的是代理对象,而不是被代理对象。同理:通过代理对象实现代理事务,大大的保障了被代理对象信息安全。
上面就是静态代理。我们设想一下,现在我们代理对象是程序员在知道被代理对象信息之后,手动创建的代理类。那要是系统里面有很多需要带的对象,使用静态代理是不是需要手动创建很多代理对象才行。这样代理冗余太多。太杂了,而且太耗资源了。那么有没有一种方法,可以不用手动创建代理对象,虽然我事先不知道被代理对象,但是我可以通过传参数的形式动态的去创建代理类呢?
答案是肯定的:这就是我们接下来要说的动态代理。至于静态代理和动态代理的区别上面都说过了,也容易理解:动态创建代理类。
那么需要怎样去动态的去实现动态代理内呢? 想一想: 1.需要动态创建代理类,那就需要能动态构造类,那我们可以使用到java的类类加载器ClassLoader。 2.之前说了代理类最终还是使用的被代理对象的方法,但是现在代理对象我们是参数传入的,我们实现不知道需要代理啥类,有什么方法。所以我们需要从参数类中获取这些信息。那我们可以用到java的类反射机制。被代理接口public interface SayToWatchTv { public void sayToWatchTv();}被代理对象实现类/** * 代理对象-- 小明 on 2021/3/23. */public class NoProxyClass implements SayToWatchTv{ public void sayToWatchTv() { System.out.println("小美我们去看电影吧"); }}代理类/** * Created by Administrator on 2021/3/23. */public class ProxyDT implements InvocationHandler{ //这个就是我们要代理的真实对象 SayToWatchTv sayToWatchTv; // 被代理对象接口 //构造方法,给我们要代理的真实对象赋初值 public SayToWatchTv getProxy(SayToWatchTv sayToWatchTv) { // 用于构建代理类 this.sayToWatchTv = sayToWatchTv; Object proxy = Proxy.newProxyInstance(sayToWatchTv.getClass().getClassLoader(), // 类加载器 sayToWatchTv.getClass().getInterfaces(),// 反射机制获取类信息 this); //被代理对象接口 return (SayToWatchTv) proxy; } // 用于出发调用代理事务 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object res = method.invoke(sayToWatchTv,args); return res; }public class MainClass { public static void main(String[] args) { ProxyDT proxyDT = new ProxyDT(); // 初始化代理类 NoProxyClass noProxyClass =new NoProxyClass(); // 需要被代理的类 SayToWatchTv sayToWatchTv = proxyDT.getProxy(noProxyClass); sayToWatchTv.sayToWatchTv(); }}}
结果
动态代理有几个核心点: 1.动态构建代理类。 Proxy.newProxyInstance 2.main方法中调用sayToWatchTv时,就是触发了invoke方法.而该方法的 本质就是调用了被代理的是实现方法。 所以动态代理实现的原理其实就是静态代理的原则,只是运用了类加载器和反射等机制,实现动态创建代理类。 上面说的JDK实现的动态代理。还有中方式是基于CGLIB的动态代理,这个后面再说。转载地址:http://sjhof.baihongyu.com/