java代理简单理解

一、什么是代理

举例说明:当我想买一台电脑,国内太贵了。委托好友A在国外帮忙买。

这个情节中我要实现的动作和好友实现的动作一样,都是买电脑。好友帮我完成了这个动作,这就是代理。

类A和类B都实现一个interface接口C,C规定了A和B要完成的动作。借助B类实现A类完成接口中的动作。

1.使用代理的场景?

(1)功能增强:B完成接口中的动作之余还做了别的事情

(2)控制访问:B不让A访问到目标类,只有通过B这个媒介,A才能访问

二、静态代理

静态代理就是:自己写类实现代理。

思路:一个接口C,一个代理类B,一个被代理类A。两个类都实现接口C,在B实现接口中的方法时调用A对象方法。

接口C:

复制代码
public interface Singer {
    void singing();
    int dance();
}

被代理类A

复制代码
public class Cai implements Singer {
    @Override
    public void singing() {
        System.out.println("cai 唱歌");
    }

    @Override
    public int dance() {
        System.out.println("tiaowu");
        return 0;
    }
}

代理类A

复制代码
public class Caidaili implements  Singer{
    private Singer cai = new Cai();
    @Override
    public void singing() {
        System.out.println("先收钱");
        cai.singing();
    }

    @Override
    public int dance() {
        System.out.println("先收钱");
        cai.dance();
        return 0;
    }
}

测试

复制代码
public class Main {
    public static void main(String[] args) {
        Singer singer = new Caidaili();
        singer.singing();
        singer.dance();
    }
}

静态代理的局限性:如果被代理类太多了,每个被代理类都要有一个代理。这样写的代理类就太多了。因此引入动态代理,动态决定被代理类。

三、动态代理

动态代理就是不需要自己写代理类了,通过反射或者继承实现。动态代理有两种模式:

(1)jdk动态代理

通过反射类实现代理

核心代码:

Proxy.newProxyInstance(被代理的类的类加载器,被代理类实现的接口,实现InvocationHandler的类对象)

返回:代理类对象

参数列表中:InvocationHandler接口(函数式接口)重写了invoke方法,重写代码中的核心:

复制代码
被代理对象.方法()

method.invoke(接口对象,参数)                  //表示调用这个接口中的方法

实例:

接口

复制代码
public interface Singer {
    void dance();
    int singing();

}

被代理类

复制代码
public class Cai implements Singer {
    @Override
    public void dance() {
        System.out.println("Cai 在跳舞");
    }

    @Override
    public int singing() {
        System.out.println("Cai 在唱歌");
        return 0;
    }
}

jdk动态代理实现

复制代码
public class Test1 {
    public static void main(String[] args) {
        Cai cai =new Cai();
//        Ruler ruler = new Ruler(cai);
        //构建了 以原被代理类为基准的代理类的一个对象
        // o 已经等同于 Student s = new Student(); 这个s了
        Object o = Proxy.newProxyInstance(Cai.class.getClassLoader(), new Class[]{Singer.class}, (proxy, method, args1) -> {
            System.out.println(proxy.getClass().toString());
            System.out.println("先收钱");
            Object returnVal = method.invoke(cai, args1);
            System.out.println("asdfasdf");
            return returnVal;
        });
        System.err.println(o.getClass().toString());
        if(o instanceof Singer){
            Singer singer =  (Singer)o;
            singer.dance();
            singer.singing();
            singer.toString();
        }
    }
}

(2)cglib动态代理

不写接口,通过继承关系重写方法实现代理

示例:

被代理类:

复制代码
public class Singer {
    public void dance(){
        System.out.println("tiaowu");
    }
    public int singing(){
        System.out.println("changge");
        return 100;
    }
}

代理类:

复制代码
public class SingerSub extends Singer {
    @Override
    public void dance() {
        System.out.println("shouqian");
        super.dance();

    }

    @Override
    public int singing() {
        System.out.println("shouqian");
        return super.singing();
    }
}

测试:

复制代码
public class Main {
    public static void main(String[] args) {
        Singer singer = new SingerSub();
        singer.singing();
        singer.dance();
    }
}
相关推荐
亮子AI20 小时前
【NestJS】在 nest.js 项目中,如何使用 Postgresql 来做缓存?
开发语言·缓存·node.js·nest.js
图灵信徒20 小时前
R语言数据结构与数据处理基础内容
开发语言·数据挖掘·数据分析·r语言
oioihoii20 小时前
高性能推理引擎的基石:C++与硬件加速的完美融合
开发语言·c++
weixin_4569042720 小时前
基于C#的文档处理
开发语言·c#
沐浴露z21 小时前
一篇文章详解Kafka Broker
java·分布式·kafka
Nero1821 小时前
代码随想录二刷第二十一天 | 222.完全二叉树的节点个数、110.平衡二叉树、257. 二叉树的所有路径、404. 左叶子之和、513.找树左下角的值
java
扶苏-su21 小时前
Java---StringBuilder
java·开发语言
我来整一篇21 小时前
[java] JVM 内存泄漏分析案例
java·开发语言·jvm
程序员黄同学21 小时前
解释 Python 中的属性查找顺序(Attribute Lookup Order)
开发语言·python
程序员鱼皮21 小时前
前后端分离,千万别再搞错了!
java·前端·后端·计算机·程序员·编程·软件开发