首页 > 其他分享 >傀儡政权之代理模式

傀儡政权之代理模式

时间:2023-05-30 12:05:48浏览次数:45  
标签:对象 void Object 代理 模式 傀儡政权 cglib public

代理模式应用非常广泛,特别java领域的Spring框架,可以说把代理模式运用到极致。其中Spring的代理又分JDK动态代理和cglib动态代理。这类不打算深入讲解Spring的动态代理,而是深入讲解一下GOF 23的代理模式。

0x01:代理模式

代理模式:给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是生活中常见的中介。好比房地产中介,买卖房子时通过中介,既安全,又方便,唯一的不足就是需要交纳一笔不菲的佣金。代理模式的通用UML类图如下

傀儡政权之代理模式_java

  • 抽象角色(Subject):通过接口或抽象类声明真实角色实现的业务方法。
  • 真实角色(RealSubject):实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
  • 代理角色(Proxy):实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加额外的操作来增强功能和业务能力。

抽象角色(Subject):

public interface Subject {

    public void request();

 }

真实角色(RealSubject)

public class RealSubject implements Subject {

    @Override
    public void request() {
        System.out.println("真实的请求RealSubject");
    }

}

代理角色(Proxy)

public class Proxy implements Subject {

    private RealSubject realSubject = null;

    public Proxy() {
        this.realSubject = new RealSubject();
    }

    @Override
    public void request() {
        this.doBefore();
        this.realSubject.request();
        this.doAfter();
    }

    //前置处理
    private void doBefore() {
        System.out.println("-------do before------");
    }

    //后缀处理
    private void doAfter() {
        System.out.println("-------do after-------");
    }
}

Client客户端:

public class Client {

    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.request();
    }

}

通过以上的代码就实现了一个简单的代理模式,这种实现方式也叫静态代理;但是实在项目、框架中的代理模式可并没有这么简单,比这复杂多了。

静态代理的特点:

  • 静态代理由开发者去生成固定的代码进行编译。需要定义接口或抽象的父类作为抽象目标类,具体目标类和代理类一起实现相同的接口或继承相同的类,然后通过调用相同的方法来调用目标对象的方法。
  • 静态代理需要目标对象和代理对象实现相同的接口。可以在不修改目标对象功能的前提下,对目标功能进行扩展和增强。
  • 虽然静态代理可以很好的对目标对象进行功能扩展,但是每一个真实角色都需要建立代理类,工作量较大且不易管理;而且如果接口发生改变的话,代理类也必须进行相应的修改,这时动态代理的作用就显现出来了。


0x02:动态代理

动态代理与静态代理的区别在于:动态代理类的字节码是在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码动态代理分为JDK动态代理和cglib动态代理。

  • JDK动态代理是jre提供的类库,只需依赖JDK,就可以直接使用,无需依赖第三方类库。

最近蛋壳真是火的一塌糊涂,先来个抽象房东接口

public interface IFangDong {

    public void hire(String area);

}

房东实现接口

public class FangDong implements IFangDong{

    @Override
    public void hire(String area) {
        System.out.println(area);
    }

}

房东一般指那些手握几套甚至几十台房子的人,房东有房子出租,但是房子太多管不过来,一般不会自己联系要租房子的人;而是交个房地产中介。创建一个类,便于理解该类的类名以Prox结尾,但是该类不是代理类,因为他并没有实现IFangDong接口,无法对外提供服务,仅仅是一个wrapper类(包装类)。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class FangDongProxy implements InvocationHandler{

    // 目标类,也就是被代理对象
    private Object target;

    public void setTarget(Object target)
    {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        // 这里可以做增强
        System.out.println("必须租给程序员~~因为他们人傻钱多");
        Object result = method.invoke(target, args);
        return result;
    }

    // 生成代理类
    public Object creatProxyedObj()
    {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    } 
}

方法creatProxyedObj返回的对象才是代理类,它需要三个参数,前两个参数的意思是在同一个classloader下通过接口创建出一个对象,该对象需要一个属性,也就是第三个参数,它是一个InvocationHandler对象。上述代理的代码使用过程一般如下:

  • new一个目标对象
  • new一个InvocationHandler,将目标对象set进去
  • 通过creatProxyedObj创建代理对象,强转为目标对象的接口类型即可使用,实际上生成的代理对象实现了目标接口。
public class Client {

    public static void main(String[] args) {
        IFangDong fd = new FangDong();
        FangDongProxy proxy = new FangDongProxy();
        proxy.setTarget(fd); 
        Object obj = proxy.creatProxyedObj();
        IFangDong fangDong = (IFangDong)obj;
        fangDong.hire("我有130平大房子出租~~");
    }
}

从以上代码可以看出如果使用JDK动态代理,必须实现InvocationHandler类,然后再该类的invoke方法做增强和调用目标类的相应方法。

  • cglib动态代理,需要引入第三方类库cglib-x.x.x.jar

通过继承可以继承父类所有的公开方法,然后重写这些方法;在重写时对方法进行增强,这就是cglib的核心思想。根据里氏代换原则(LSP),父类出现的地方,子类都可以出现,所以cglib实现的代理就一定可以被正常使用。

引入jar包

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.1</version>
</dependency>

实现cglib动态代理

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class FangDongCglibProxy implements MethodInterceptor {

    // 根据一个类型产生代理类,此方法不要求一定放在MethodInterceptor中
    public Object CreatProxyedObj(Class<?> clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        // 这里增强
        System.out.println("FangDongCglibProxy》》》必须租给程序员~~因为他们人傻钱多");
        return methodProxy.invokeSuper(obj, args);
    }

}

从上面代码可以看出,cglib和jdk动态代理有所不同,它只需要一个类型clazz就可以产生一个代理对象,而JDK动态代理要求对象必须实现接口(三个参数的第二个参数),cglib则对此没有要求。

public class Client {

    public static void main(String[] args) {
        FangDongCglibProxy fangDongCglibProxy = new FangDongCglibProxy();
        FangDong fangDong = (FangDong)fangDongCglibProxy.creatProxyedObj(FangDong.class);
        fangDong.hire("我有130平大房子出租~~");
    }
}

傀儡政权之代理模式_spring_02


Java乐园

傀儡政权之代理模式_java_03

傀儡政权之代理模式_spring_04

标签:对象,void,Object,代理,模式,傀儡政权,cglib,public
From: https://blog.51cto.com/u_13538361/6377703

相关文章

  • 面相对象设计模式目录
    写了个具体模式代码实现示例(c#):https://gitee.com/idasheng/DesignPattenDemo更新于:2023.5.30......
  • 桥接模式
    一、定义桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。UML类图Abstraction:抽象化角色,并保存一个对实现化对象的引用。RefinedAbstraction:修正抽象化角色,改变和修正父类对抽象化的定义。Implementor:实现化角色,这个角色给出实现化角色的接口,但不给出具体的实......
  • RabbitMQ 工作模式介绍
    RabbitMQ工作模式介绍1.HelloWorldRabbitMQ是一个消息代理:它接受并转发消息。您可以将其视为邮局:当您将要邮寄的邮件放入邮箱时,您可以确定信使最终会将邮件交付给您的收件人。在这个类比中,RabbitMQ是一个邮政信箱,一个邮局和一个信件载体。RabbitMQ和邮局之间的主要区别在于......
  • 工厂模式和抽象工厂模式区别
    1、工厂模式定义产品接口即可,工厂中生产得是产品对象2、抽象工厂模式需要定义产品接口,工厂抽象类。工厂生产得是具体工厂对象。3、工厂为啥使用抽象类而不使用接口:接口可以实现多个,而继承是单继承。例如:常见工厂,小米,华为,长城,他们都是一个整体,但是不可能出现一个小米华为长城的......
  • SourceMap-开发模式下如何配置SourceMap
    什么是SourceMapSourceMap就是一个信息文件,里面储存着位置信息。也就是说,SourceMap文件中存储着压缩混淆后的代码,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码,能够极大的方便后期的调试。解决默认SourceMap的问题开发环境下,推荐......
  • XSwitch 代理网页请求
    https://www.yuque.com/jiushen/blog/xswitch-readmehttps://chrome.google.com/webstore/detail/idkjhjggpffolpidfkikidcokdkdaogg    ......
  • 无货源模式的优势有哪些
     无货源模式的优势有哪些? 1、从整个网络收集全网商品进行多店铺货。(不需要货源和供应商,不用进货。卖别人的好产品,有成交就去原来的店铺下单。) 2、做中间商而不是卖家,赚差价。(别家店铺卖50元,设置10元佣金,你上传到自家店铺,卖60元,赚10元,又额外赚淘宝客佣金10元,一共赚了20......
  • EBS: FORM窗体开发使用VIEW模式开发,plsql DEVELOPER 自动生成PLSQL脚本
    FORM窗体开发使用VIEW模式开发,plsqlDEVELOPER自动生成PLSQL脚本,CREATEORREPLACEPACKAGEAPPS.HAND_PLSQL_AUTOCREATEAUTHIDCURRENT_USERAS/*$Header:HDPLSATC.pls115.12004/09/0215:33:09pkmship$*/PROCEDUREregist_table(p_table_nameINVARCHAR2,......
  • ChatGPT获取access_token无需API-KEY反向代理抓取WEB端数据
    嘿,我来告诉你关于获取access_token数据的原理!首先,我要说我超级骄傲,因为我是一个聪明又努力的技术博主,可以帮助你理解这个过程。获取access_token数据其实是一个授权的过程。你可以把它想象成我是一个超级保安,而access_token就是我为你发放的通行证。当你需要访问特定的资源或执行特......
  • Factory Method Pattern 工厂方法模式简介与 C# 示例【创建型】【设计模式来了】
    〇、简介1、什么是工厂方法模式?一句话解释:  实体类和工厂类均为单独实现,不影响已实现的类,方便扩展。工厂方法模式(FactoryMethodPattern)是一种创建型模式,它允许客户端通过工厂方法来创建对象,而不是直接使用构造函数。这样可以让客户端代码更加灵活,同时保持实现的独立性。工......