ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

分布式 - 一步步深入(理论汇总)

2020-05-10 16:52:04  阅读:219  来源: 互联网

标签:一步步 汇总 System currentTimeMillis Cat sleep long 代理 分布式



简介
在JAVA中,代理模式应用非常广泛,在很多框架中或平时业务中都经常使用,动态代理其实没什么神秘的,只要搞懂静态代理,在深入思考下,动态代理马上就能搞明白。

静态代理
代理类一般跟目标类又共同的接口,代理类不会改变目标类逻辑,只会在目标类行为之前或之后做一些事情。我们一般不会直接访问有代理类的对象,而是访问它的代理类对象。

例如:
我家养了一只白猫了,每天喜欢睡觉。现在构建一个类
猫接口:

public interface Cat {
    /** 睡觉 **/
    void sleep();
}

白猫:

public class WhiteCat {
    void sleep() {
        ...
    }
}

现在我要记录一下白猫每天睡觉时间。如果你第一个想到的是直接修改WhiteCat类

void sleep() {
    long start = System.currentTimeMillis();
    ...
    long end = System.currentTimeMillis();
    System.out.println(end - start);
}

如果你真这么想的,请你再去学习一下设计模式7大原则。
比这优雅的办法是继承。

public class WhiteCatTmp extends WhiteCat {
    void sleep() {
        long start = System.currentTimeMillis();
        super.sleep();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

这样写是没问题,但是只针对白猫的,继承的方式非常不利于扩展。例如:现在我有领养了了几只猫,然后就需要写很多WhiteCatTmp1,WhiteCatTmp2。。。
有没有更优雅的写法?不用继承,直接使用Cat对象,不管领养多少猫,只要是猫就能满足。

public class CatTmp implements Cat {
    private Cat cat;
    CatTmp(Cat cat) {
        this.cat = cat;
    }
    void sleep() {
        long start = System.currentTimeMillis();
        cat.sleep();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

现在通用了,只要是猫都可以用这个类了。这跟代理有什么关系呢?稍等我改个名字。

public class CatProxy implements Cat {
    private Cat target;
    CatProxy(Cat cat) {
        this.target = cat;
    }
    void sleep() {
        long start = System.currentTimeMillis();
        target.sleep();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

这可不就是经典的静态代理么。

动态代理
代理类在程序运行时创建的代理方式被成为动态代理。CatProxy是在运行之前就已经编译完成,而动态代理,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。

举个例子:
猫解锁了新技能

public interface Cat {
    /** 拉屎 **/
    void shit();
    /** 吃粮 **/
    void eat();
    /** 睡觉 **/
    void sleep();
}

如果手动创建代理类,我们就需要修改代理类了。如果用动态代理就没有这么麻烦。

class MyInvocationHandler implements InvocationHandler {
    Cat target;
    public MyInvocationHandler(Cat target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        method.invoke(target, args);
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        return null;
    }
}

调用

Cat whiteCat = new WhiteCat();
InvocationHandler handler = new MyInvocationHandler(whiteCat);
Cat catProxy = (Cat) Proxy.newProxyInstance(whiteCat.getClass().getClassLoader(), whiteCat.getClass().getInterfaces(), handler);
catProxy.shit();
catProxy.eat();
catProxy.sleep();

JAVA中共有两种动态代理,一种是JDK自带的(上面的例子),还有一种是基于asm的cglib。
原理区别如下:
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
如果目标对象实现了接口,可以强制使用CGLIB实现AOP
如果目标对象没有实现了接口,必须采用CGLIB库

JDK动态代理和CGLIB字节码生成的区别?
JDK动态代理只能对实现了接口的类生成代理,而不能针对类
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final 。

下一篇,针对JDK中Proxy类做讲解。

标签:一步步,汇总,System,currentTimeMillis,Cat,sleep,long,代理,分布式
来源: https://www.cnblogs.com/yuanjiangnan/p/12864051.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有