设计模式之动态代理

7 篇文章 0 订阅
7 篇文章 0 订阅

1 背景回顾

设计模式是一种思维方式,前人总结的最佳实践,也是一种态度,一种进步。
软件过程里面设计模式一共有23种,一般分为3类。即创建型,结构性型,行为型。其中:

创建型5种: 解决了创建对象的烦恼
单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式

结构性型7种: 解决了如何让类组合起来完成复杂的功能
适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式,

行为型11种: 解决了类之间的控制关系。
模版方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,状态模式,策略模式,职责链模式,访问者模式,解释器模式。

如果想要学习并掌握这些设计模式,最好是编码和画图理解。

在学习动态代理之前,最好先学习静态代理,可以看笔者另外一篇基础文章:设计模式之静态代理

2 动态代理

因为静态代理对每个要被代理的类,都要创建一个对应的类,比较麻烦。由此,提出了动态代理,即一个代理可以代理多个真实的类。
需要用到3个类,InvokerHanlder接口,Proxy,前者要使用invoke方法,后者完成生成对应真实类的代理。

2.1 要代理的接口
租房

package demo03;

public interface Rent {
    void rent();
}

2.2 真实的角色:房东

package demo03;


public class Host implements Rent {
    public void rent() {
        System.out.println("房东要租房");
    }
}

2.3实现InokerHanlder接口

第一步: 定义被代理的接口
第二步:生成得到代理,通过Proxy.newProxyInstance(ClassLoader,Interfaces,InvokerHanlder),参数分别分类加载器,接口对象,InvokerHanlder
第三步:处理代理实例,并返回结果

package demo03;

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

//代理 调用处理器
public class ProxyInvocationHandler implements InvocationHandler {
    // 1 定义被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }
//2  生成得到代理
  public Object  getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }
    //3 处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(rent, args);//类似于,rent.method(args)
        return result;
    }
}

2.4 客户端找代理

package demo03;



public class Client {
    public static void main(String[] args) {
        //需要先生成一个真实代理的类
        Rent host = new Host();

        //代理角色, 现在没有
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        //通过调用处理角色来处理我们要调用的接口对象
        proxyInvocationHandler.setRent(host);
        // 动态生成代理
        Rent proxy = (Rent) proxyInvocationHandler.getProxy();
        proxy.rent();
    }
}

执行结果:
在这里插入图片描述

3 动态代理进阶

对与第3个角色生成,可以写成一个通用工具类,以后使用时直接用就好了,即达到可以代理很多对象的初衷。

即把Rent接口变为Object就可以了。这个工具类可以代理很多类型对象。

package demo04;

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

//代理 调用处理器
public class ProxyInvocationHandler implements InvocationHandler {
    // 1 定义被代理的接口
    private Object target;

    public void setRent(Object target) {
        this.target = target;
    }
//2  生成得到代理
  public Object  getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    //3 处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       // 方法执行前
        Object result = method.invoke(target, args);//类似于,rent.method(args)
          // 方法执行后
        return result;
    }
}

同时,在方法执行前后还能加一些方法:

 // 方法执行前
        Object result = method.invoke(target, args);//类似于,rent.method(args)
          // 方法执行后

具体如下:

package demo04;

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

//代理 调用处理器
public class ProxyInvocationHandler implements InvocationHandler {
    // 1 定义被代理的接口
    private Object target;

    public void setRent(Object target) {
        this.target = target;
    }
//2  生成得到代理
  public Object  getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    //3 处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);//类似于,rent.method(args)
        after();
        return result;
    }


    public  void before(){
        System.out.println("==========invoke方法执行前======");
    }

    public  void after(){
        System.out.println("=====invoke方法执行后=====");
    }
}


执行结果:
在这里插入图片描述
接口里面如果有多个方法,在使用proxy.xxx()执行前后都会打印出来,这就是AOP的底层。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值