Dubbo中的代理模式:所谓代理模式,简单点说就是调用端不能直接引用某个服务,通过一个中介角色来间接调用这个服务,而这个中介就是充当 着代理的角色,去调用服务端的。 Java中的代理总体上分为两种:一种是静态代理,二种是动态代理 1、静态代理就很简单了,就是通过硬编码方式(不知道这样形容对不对)写一个实际存在的代理角色,去间接的调用服务方法。 2、动态代理是相对于静态代理而言,因为静态代理使用过程中都要产生一个代理角色,这明显是不科学的,因为在使用中会产生大理的代理类。 因此,动态代理的优势就很明显了,在Java体系中,可以细分为两种动态代理,一种JDK的原生动态代理,另一种是基于CGLIB(Code Generation Library)方式的动态代理,区别就是JDK代理只能针对接口类代理,而CBLIB可以对具体类实现代理,单纯从效率上看,单例的对象似乎CGLIB会比JDK快一些,而对于final方法,无法进行代理。 这理要提一下:大量的使用CGLIB动态代理可能会导致虚拟机方法区溢出,因为会动态的产生class文件,可以用VisualVM观察一下,这个工作JDK中自带的哈。 JDK代理:这里面要用到InvocationHandler 接口,很简单里面只有一个方法,以及Proxy类,这个类是关键所在。 有一个思考题:为什么JDK代理只能对接口方式实现代理,呵呵,仔细看看还是很有意思的这里就不说了。 CGLIB方式:通俗讲,运用字节码技术创建一个类的子类,主要就是实现这个接口MethodInterceptor,里面只有一个方法,使用前先用Maven引入cglib包。
下面是举的例子:
public interface ProxyInterface { void sendEmail(); }public class ProxyInterfaceImpl implements ProxyInterface { @Override public void sendEmail() { System.out.println("发到北京去!"); } }public class RealProxy implements ProxyInterface { private ProxyInterface proxy; public RealProxy() { this.proxy = new ProxyInterfaceImpl(); } @Override public void sendEmail() { System.out.println("同志你好!"); proxy.sendEmail(); } }public class DynamicProxy implements InvocationHandler { //对真实对象的引用 private Object o; public DynamicProxy(Object o) { this.o = o; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("我也可以说:同志你好!"); return method.invoke(o, args); } }public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz){ enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("除了你们,我也可以说:同志你好"); return proxy.invokeSuper(obj, args); } }public class TestMain { public static void main(String[] args) { /* 静态代理*/ ProxyInterface proxy = new RealProxy(); proxy.sendEmail(); /* JDK动态代理*/ DynamicProxy handler = new DynamicProxy(new ProxyInterfaceImpl()); ProxyInterface proxyInterface = (ProxyInterface) Proxy.newProxyInstance(handler.getClass() .getClassLoader(), new ProxyInterfaceImpl().getClass().getInterfaces(), handler); proxyInterface.sendEmail(); /* CGLIB动态代理*/ CglibProxy cglicbProxy = new CglibProxy(); ProxyInterfaceImpl cglibImpl = (ProxyInterfaceImpl) cglicbProxy.getProxy(ProxyInterfaceImpl.class); cglibImpl.sendEmail(); } }结果:同志你好! 发到北京去! 我也可以说:同志你好! 发到北京去! 除了你们,我也可以说:同志你好! 发到北京去! Process finished with exit code 0
读懂Dubbo源码必备知识点之三
最新推荐文章于 2021-03-18 16:31:46 发布