代理模式-静态代理与动态代理

简介

  • 首先感谢沽泡学院 tom 老师
  • 代理模式是一种结构型模式
  • 代理模式就是代理对象帮被代理对象处理一些问题, 类似中介, 客户只要结果, 中介怎么搞是他的事儿, 他可能再处理过程中赚外快什么的
  • 代理模式的应用: spring中的aop, 日常工作中记录日志, 统计时间,权限控制等
  • 这里我们使用一个客户端代理访问google举例, 具体细节可能不合适, 意会、意会、意会...

静态代理

/**
 * 一个服务器接口, 服务器有很多功能, 可以用来路由, 建站等...
 */
public interface Server {
    boolean internetgoogle(Boolean ispass);
    boolean internetbaidu(Boolean ispass);
}
/**
 * @ClassName: HKProxyServer
 * @description [静态代理类, 帮助被代理对象访问url, 静态代理类和被代理对象实现同一接口, 唯一的区别就是代理类持有被代理对象引用, ]
 *  每次修改接口, 代理类和被代理类都要实现相同的方法, 静态代理, 要做的事情已经是确定的, 只是表面上换了个人去做
 * @create 2018-03-31 上午7:56
 **/
public class HKProxyServer implements Server{

    //传入客户端信息
    private Server client;

    public HKProxyServer(Server client) {
        this.client = client;
    }

    @Override
    public boolean internetgoogle(Boolean ispass) {
        System.out.println("香港代理: ");
        return client.internetgoogle(true);
    }

    @Override
    public boolean internetbaidu(Boolean ispass) {
        System.out.println("香港代理: ");
        return client.internetbaidu(true);
    }
}
/**
 * @ClassName: ChinaServer
 * @description [描述该类的功能]
 * @create 2018-03-31 上午7:45
 **/
public class ChinaClient implements Server {

    @Override
    public boolean internetgoogle(Boolean ispass) {
        if(ispass != null && ispass){
            System.out.println(" 请求地址: www.google.com 通过");
            return true ;
        }else{
            System.out.println(" 请求地址: www.google.com 拒绝");
            return false;
        }
    }

    @Override
    public boolean internetbaidu(Boolean ispass) {
        System.out.println(" 请求地址: www.baidu.com 通过");
        return true;
    }
}
public class AccessGoogle {

    @Test
    public void tryToAccessGoogle(){
        Server chinaServer = new ChinaClient();
        //访问不了google
        Assert.assertFalse(chinaServer.internetgoogle(null));
        //可以访问baidu
        Assert.assertTrue(chinaServer.internetbaidu(null));

        System.out.println("--------------------------------------------------通过代理访问--------------------------------------------------");
        Server proxyServer = new HKProxyServer(chinaServer);
        //可以访问google
        Assert.assertTrue(proxyServer.internetgoogle(null));
        //可以访问baidu
        Assert.assertTrue(proxyServer.internetbaidu(null));

    }
}

jdk实现动态代理

/**
 * @ClassName: HKProxyServer
 * @description [使用jdk动态代理实现, 不用实现与被代理类相同的接口, 接口增加方法也与我无关, 动态调用被代理类方法,
 *                  在调用方法前我可以输出日志, aop, 但是调用的方法的对象是传入的client对象]
 * @create 2018-03-31 上午7:56
 **/
public class HKProxyServer implements InvocationHandler {

    //传入客户端信息
    private Server client;

    public HKProxyServer(Server client) {
        this.client = client;
    }

    public Object getInstence(){
        Class<?> clazz = client.getClass();
        //用来生成一个新的对象(字节码重组来实现)
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);

        //如果直接返回传入对象就不会调用下面的invoke方法
//        return client;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        args = new Object[]{true};//代理执行方法前可以搞事情
        System.out.println("mylog +++++++++ 动态代理调用方法 " + method.getName());
        return method.invoke(this.client, args);
    }
}
/**
 * @ClassName: ChinaServer
 * @description [描述该类的功能]
 * @create 2018-03-31 上午7:45
 **/
public class ChinaClient implements Server {

    @Override
    public boolean internetgoogle(Boolean ispass) {
        System.out.println(this);
        if(ispass){
            System.out.println("请求地址: www.google.com 通过");
            return true ;
        }else{
            System.out.println("请求地址: www.google.com 拒绝");
            return false;
        }
    }

    @Override
    public boolean internetbaidu(Boolean ispass) {
        System.out.println(this);
        System.out.println("请求地址: www.baidu.com 通过");
        return true;
    }
}
public class AccessGoogle {

    @Test
    public void tryToAccessGoogle(){
        //代理对象内部使用传入de被代理对象调用方法(等价 new Object().methodxx())
        Server chinaClient = new ChinaClient();
        Server proxyServer = (Server)new HKProxyServer(chinaClient).getInstence();
        Assert.assertTrue(proxyServer.internetgoogle(false));
        Assert.assertTrue(proxyServer.internetbaidu(true));

        Assert.assertFalse(chinaClient.equals(proxyServer));
    }
}

cglib实现动态代理

/**
 * @ClassName: HKProxyServer
 * @description [使用cglib实现动态代理, 客户端都不用创建对象, 对象由框架创建载入, 体现在客户端像是用接口调用方法]
 * @create 2018-03-31 上午7:56
 **/
public class HKProxyServer implements MethodInterceptor {

    public Object getInstence(Class<?> clazz){

        Enhancer enhancer = new Enhancer();
        //要把哪个设置为即将生成的新类父类
        enhancer.setSuperclass(clazz);

        enhancer.setCallback(this);

        return  enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("mylog +++++++++++++++ cglib代理实现: 调用方法" + method.getName());
        return methodProxy.invokeSuper(o,objects);
    }
}
public class ChinaClient implements Server {

    @Override
    public boolean internetgoogle(Boolean ispass) {
        System.out.println(this);
        if(ispass){
            System.out.println("请求地址: www.google.com 通过");
            return true ;
        }else{
            System.out.println("请求地址: www.google.com 拒绝");
            return false;
        }
    }

    @Override
    public boolean internetbaidu(Boolean ispass) {
        System.out.println(this);
        System.out.println("请求地址: www.baidu.com 通过");
        return true;
    }
}
public class AccessGoogle {

    @Test
    public void tryToAccessGoogle(){
        //不需要再new对象,传入chinaclient.class即可, 然后使用接口调用方法, 内部创建了个新的子类对象来调用指定方法
        Server proxyServer = (Server)new HKProxyServer().getInstence(ChinaClient.class);
        Assert.assertTrue(proxyServer.internetgoogle(true));
        Assert.assertTrue(proxyServer.internetbaidu(true));
    }
}

三种代理方式的分析

  • 静态代理: 要做的事情已经是确定的, 只是表面上换了个人去做,代理对象和被代理对象实现同样的接口,实际通过传入对象调用
  • jdk动态代理: 与静态代理效果相同, 但是java通过反射实现代理类不用实现与被代理对象同样的接口, 也可以根据传入方法调用被代理对象的方法, 传入对象调用
  • cglib动态代理: 只需要传入被代理对象的类名, 内部会实现创建对象到调用的过程,客户端不需要创建具体的对象, 接口调用方法

代码路径

https://github.com/offline7LY/designpattern

原文地址:https://www.cnblogs.com/qq347061329/p/8683897.html

时间: 2024-12-20 18:01:59

代理模式-静态代理与动态代理的相关文章

代理模式(Java的动态代理)

(一)是什么?what? ①:定义: ②:特征:1.0代理类(中间追求者),与委托类(追求者)有同样的接口: 2.0代理类--->主要负责为委托类预处理消息.过滤消息.把消息传递给委托类,事后处理消息等.[类似:帮别人追女朋友,打探消息]. 3.0代理类与委托类之间通常会有 关联关系 [类似哥们儿].一个代理类的对象 与 一个委托类的对象关联.代理类本身不真正实现服务,而是通过调用委托类的方法,来提供特定服务.[类似于帮追的哥们  是  根据  喜欢那女孩儿的哥们儿  的要求  来做事儿]. ③

zbb20180930 代理模式 -静态代理-jdk动态代理-cglib动态代理

CGLIB与JDK动态代理区别 区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理.而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理. 1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2.如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3.如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB

Java代理模式——静态代理模式

一:代理模式 代理模式的作用是:为其他对象提供一种代理以控制这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 二:代理模式设计到的角色 抽象角色:声明真是对象和代理对象的共同接口(抽象类或接口). 代理角色:代理对象角色内部含有对真是对象的引用,从而可以操作真是对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能够代替真是对象.同时,代理对象可以在执行真实对象的操作时,附加其他操作,相当于对真是对象进行封装. 真实

性能优于JDK代理,CGLib如何实现动态代理

按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建而成. 动态代理三种方式 动态代理实现有三种方式,jdk动态代理(基于接口),cglib动态代理(基于继承),javassist(hibernate中使用这种方式)实现动态代理. JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢? 这就需要CGLib了. cgl

设计模式之动态代理(Java的JDK动态代理实现)

对于JDK的动态代理,孔浩老师说学习的方法是把它记下来. 先写一个主题接口类,表示要完成的一个主题. package com.liwei.dynaproxy; /** * 要代理的主题接口 * @author Administrator * */ public interface Subject { public void miai(); } 再写一个实现类,这个实现类实现这个接口.当然,这个实现类就是我们要代理的对象. 为了区别不同的类的对象,我们为Person类增加了一个name属性,并且通

设计模式 - 代理模式(proxy pattern) 未使用代理模式 详解

代理模式(proxy pattern) 未使用代理模式 详解 本文地址: http://blog.csdn.net/caroline_wendy 部分代码参考: http://blog.csdn.net/caroline_wendy/article/details/37698747 如果需要监控(monitor)类的某些状态, 则需要编写一个监控类, 并同过监控类进行监控. 但仅仅局限于本地, 如果需要远程监控, 则需要使用代理模式(proxy pattern). 具体方法: 1. 类中需要提供

【Java】代处理?代理模式 - 静态代理,动态代理

>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算,见[Java]Float计算不准确) package com.nicchagil.study.java.demo.No09代理.No01不用代理; import java.math.BigDecimal; public class FloatCalculator { public float add(fl

代理模式-利用JDK原生动态实现AOP

一.目录 二.概述与模型 1.概述 含义:控制对对象的访问. 作用:详细控制某个(某类)某对象的方法,在调用之前做前置处理,调用之后做后置处理,从而实现将统一流程代码放在代理类中处理. 举例:我们在学习JDBC的时候,在批量处理的时候遇到过事务.流程:设置提交方式为手动提交-开启事务-批量处理-关闭事务-设置提交方式为默认.从这里我们清晰可以看见,每次进行批处理的时候,唯有增删改操作变化,其他的操作都是一样的.那么,我们可不可以把一样的操作提取出来交给一个类处理,批量操作提取出来交给一个类实现?

代理模式(静态代理)的通俗理解

代理模式分为两种:静态代理和动态代理. 首先不谈模式,举一个例子: 有一队很美丽的妹子,她们都是训练有素的迎宾小姐.平时忙于训练再加上人脉与广告投入不多,生意并不好.于是她们的老大提议去找一个礼仪公司合作,请他们把迎宾的活儿包给她们来做.恰好在某个公司有个接待外宾的活动,该活动交给一个这个知名的礼仪公司负责,礼仪公司就通知了迎宾小姐.在外宾下车时就要乐队奏乐,走到公司门口时,迎宾小姐需要致以问候.现在来模拟一下这个情景. //相当于迎宾小姐(委托类) public class HelloWorl