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();
    }
}
相关推荐
m0_571957581 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
一点媛艺2 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风2 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程4 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk4 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*5 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go