您现在的位置是:首页 > 正文

静态代理与动态代理

2024-02-01 05:03:12阅读 6

1、代理模式的原理:

使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上

2、静态代理

实现Runnable接口的方法创建多线程。

Class MyThread implements Runnable{}          //相当于代理类

Class Thread implements Runnable{} //被代理对象

main(){

MyThread t = new MyThread();

Thread thread = new Thread(t);

thread.start();//启动线程,调用线程的run()

}

静态代理实现

package com.atguigu.java;

/**
 * @ClassName ClothFactory
 * @Description
 * @Author 小黄debug
 * @Date 2022/4/22 20:40
 * @Version 1.0
 **/
//静态代理
public class StaticProxyTest {
    public static void main(String[] args) {
        //创建被代理类的对象
        NikeClothFactory nike = new NikeClothFactory();
        //创建代理类的对象
        ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);

        proxyClothFactory.produceCloth();

    }

}

interface ClothFatory{
    void produceCloth();
}
//代理类
class ProxyClothFactory implements ClothFatory{
    private ClothFatory factory;//用被代理类对象进行实例化

    public ProxyClothFactory(ClothFatory factory){
        this.factory = factory;
    }

    public void produceCloth(){
        System.out.println("代理工厂做一些准备工作");
        factory.produceCloth();
        System.out.println("代理工厂做一些后续的收尾工作");
    }
}

//被代理类
class NikeClothFactory implements ClothFatory{
    public void produceCloth(){
        System.out.println("Nike工厂生产一批运动服");
    }
}

2.2静态代理的缺点:

1)代理类和目标对象的类都在编译期间确定下来,不利于程序的扩展。

2)每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理

3、动态代理的特点:

动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象

4、动态代理的实现:

4.1需要解决的两个问题

问题一:如何根据加载到内存中的被代理类,动态创建一个代理类及其对象

通过Proxy.newProxyInstance()实现

问题二:当通过代理类的对象调用方法a时,如何 动态的去调用被代理类中的同名方法a

通过InvocationHandler接口的实现类及其方法invoke()

4.2代理实现

在接口的情况下,使用JDK动态代理实现

package com.atguigu.java;

import javax.management.remote.rmi._RMIConnection_Stub;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @ClassName ProxyTest
 * @Description
 * @Author 小黄debug
 * @Date 2022/4/22 19:55
 * @Version 1.0
 **/


public class ProxyTest {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //SuperMan superMan = new SuperMan();
        Class<?> superManClass = Class.forName("com.atguigu.java.SuperMan");
        Object superMan = superManClass.newInstance();
        System.out.println(superMan.getClass().getName());
        //代理类的对象
        Human proxyInstance = (Human)ProxyFactory.getProxyInstance(superMan);
        String belief = proxyInstance.getBelief();
        System.out.println(belief);


        proxyInstance.eat("四川麻辣烫");

        NikeClothFactory nikeClothFactory = new NikeClothFactory();
        ClothFatory clothFatory = (ClothFatory)ProxyFactory.getProxyInstance(nikeClothFactory);
        clothFatory.produceCloth();

    }

}
/*
想要实现动态代理,需要解决的问题?
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
问题二:当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法。
 */
class ProxyFactory{
    //调用此方法,返回一个代理类的对象。解决问题一
    public static Object getProxyInstance(Object obj){//obj:被代理类的对象

        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);

        Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);

        return o;
    }
}


class MyInvocationHandler implements InvocationHandler{

    private Object obj;//赋值时,也需要使用被代理类的对象进行赋值

    public void bind(Object obj){
        this.obj = obj;
    }
    //当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()
    //将被代理类要执行的方法a的功能就声明在invoke()中
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象调用的方法。
        HumanUtil humanUtil = new HumanUtil();

        humanUtil.method1();
        //obj:被代理类的对象
        Object returnValue = method.invoke(obj, args);
        //上述方法的返回值就作为当前类的invike()的返回值
        humanUtil.method2();
        return returnValue;
    }
}

interface Human{
    String getBelief();

    void eat(String food);
}
class HumanUtil{
    public void method1(){
        System.out.println("==============通用方法1=============");
    }
    public void method2(){
        System.out.println("==============通用方法2=============");
    }
}
//被代理类
class SuperMan implements Human{

    @Override
    public String getBelief() {
        return "I believe I can fly";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃"+food);
    }
}

如需要查看CGlib动态代理及其它关于动态代理内容,请查看spring专栏

网站文章

  • 【备战金九银十】2023年最全Android岗1000+面试题及答案

    【备战金九银十】2023年最全Android岗1000+面试题及答案

    马上又准备迎接金九银十了,各大厂,国央企纷纷加入抢人大战竞争尤为激烈!但是,相比求职者来说岗位数量还不是很多,自然而然 HR 们就开始优中选优,激化“内卷”!如何在众多面试者中脱颖而出?对于很多程序员来说是目前最重要的事。因此本篇通过收集腾讯T4总结的2023年最全的Android岗1000+面试题及答案,旨在为大家提供重要参考,帮助你更好地准备新的面试。

    2024-02-01 05:02:44
  • First image then video A two-stage network for spatiotemporal video denoising

    First image then video A two-stage network for spatiotemporal video denoising

    问题:现存的去噪算法容易,即当对象快速移动时,光流计算失误,造成运动对象的边界会变得模糊关于运动模糊的说明:the boundary of a moving object tends to appea...

    2024-02-01 05:02:37
  • Django之ORM操作

    **Queryset数据类型** QuerySet与惰性机制 所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它...

    2024-02-01 05:02:29
  • 2_5_LeetCode刷题总结(基本算法)动态规划

    2_5_LeetCode刷题总结(基本算法)动态规划

    编程总结 每每刷完一道题后,其思想和精妙之处没有地方记录,本篇博客用以记录刷题过程中的遇到的算法和技巧 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 注意你不能在买入股票前卖出股票。 输入: [7,1,5,3,6,4] 输出: 5 解释: 在第 2 天(股票价格 = 1)的时...

    2024-02-01 05:02:21
  • 浅显易懂的《C++类和对象》-中篇

    内容充实、概念易懂,C++类和对象中篇,类的6个默认成员函数,轻松掌握。

    2024-02-01 05:01:51
  • 「Active Directory Sec」白银票据和黄金票据

    「Active Directory Sec」白银票据和黄金票据

    白银票据: 即伪造的TGS。当获取需要访问的目标服务器NTLM HASH后,就可以利用Mimikatz伪造TGS,直接去访问目标服务器。此过程不需要KDC的参与。但缺点是只能访问一个服务。黄金票据: ...

    2024-02-01 05:01:44
  • Day3.数据可视化-- 可视化基础

    Day3.数据可视化-- 可视化基础

    可视化主要是以图像来展示数据间的关系,常见的图形种类有折线图,散点图,条形图,直方图,饼图。此外在接下来课程中还会用到箱线图,热力图,蜘蛛图,表示二元变量分布和成对关系的视图。学好可视化...

    2024-02-01 05:01:37
  • C++ 内存分区: 代码区 全局区 栈区 堆区

    C++ 内存分区: 代码区 全局区 栈区 堆区

    1.代码区: 存放函数体的二进制代码,由操作系统进行管理 **2.全局区:**存放全局变量和静态变量以及常量,数据在程序结束后由操作系统释放 存放内容:全局变量、静态变量、常量区(字符串常量和其他常量) **3.栈区:**由编译器分配和释放,存放函数的参数值,局部变量等 **4.堆区:**由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收 ...

    2024-02-01 05:01:10
  • Android中 Bitmap Drawable Paint的获取、转换以及使用

    比如Drawable中有一系列连续的图片,img_0.png, img_1.png, img_2.png ... 如果要动态获取这些图片,通过&quot;R.drawable.img_x&quot;的...

    2024-02-01 05:01:03
  • 【靶场平台】一些免费好用的靶机渗透测试环境

    1、Vulhub: (各种漏洞环境集合,一键搭建漏洞测试靶场) https://vulhub.org/(在线版) https://github.com/vulhub/vulhub(离线版) 2、Vul...

    2024-02-01 05:00:55