创建型模型——代理者模式(Proxy Pattern)

代理模式的概念

代理模式在不改变原有类的基础之上,可以对类中的方法进行扩展。其中的核心业务流程还是通过委托类进行完成,但是在业务处理之前可以增加 一个请求过滤,请求校验,业务处理之后的一些后续处理方法,==侧重于对业务流程的一个控制。==而且代理模式的代理关系是确定的,用户不需要额外的指定实际的委托类。
利用代理模式可以保证程序高内聚的特点,比如在Spring AOP的面向切面编程当中,通过代理机制对目标类的方法扩展,实现代码织入。

相关类图

在这里插入图片描述

静态代理和动态代理

静态代理的代理类在编译时就已经存在于代理类的字节码中,而动态代理的代理类是在程序的运行过程当中,通过反射机制动态生成的。

静态代理

优点:实现简单,理解简单
缺点:需要代理所有方法,不想代理的方法也需要代理

程序实现:

  1. 先定义一个统一接口
package Proxy;

/**
 * 打印机功能
 */
public interface Printer {
    void print();

    void input();
}

2、定义具体的核心业务处理类(委托类)

package Proxy;

public class PrinterImpl implements Printer{
    @Override
    public void print() {
        System.out.println("打印机正在打印输出");
    }

    @Override
    public void input() {
        System.out.println("打印机正在接受输入");
    }
}

3、创建静态代理类

package Proxy;

/**
 * 静态代理和委托者需要实现同样的接口
 */
public class StaticProxy implements Printer{
    Printer printer = null;
    public StaticProxy(Printer printer){
        this.printer = printer;
    }
    @Override
    public void print() {
        System.out.println("先检查上一个任务是否完成");
        printer.print();
    }

    @Override
    public void input() {
        //这个方法其实不需要代理,但是静态代理都需要代理
        printer.input();
    }
}

4、定义静态工厂,代理关系已经确定了,不需要用户传入不同的委托类

package Proxy;

/**
 * 静态代理工程
 */
public class StaticProxyFactory {
    public static Printer getInstance(){
        return new StaticProxy(new PrinterImpl());
    }
}

5、客户端调用

package Proxy;

public class Client {
    public static void main(String[] args) {
        Printer instance = StaticProxyFactory.getInstance();
        instance.print();
        instance.input();
    }
}

java动态代理

java提供远程的动态代理类Proxy,动态代理可以只代理需要代理的方法,不需要代理的方法可以不管,简化了编码
java是基于接口实现的动态代理,如果委托类没有实现接口,动态运行时会报错。

相关API

Proxy.newInstance(classLoader,interfaces,invocationHandler)
项目Value
classLoader指定动态代理类使用的类加载器
interfaces委托类实现的接口数组
invocationHandler调用目标方法,扩展功能代码

程序实现

1、定义接口

package Proxy.javaActive;

/**
 * 打印机功能
 */
public interface Printer {
    void print();

    void input();
}

package Proxy.javaActive;

/**
 * 委托类的另外一个接口
 */
public interface Email {
    void send();
    void receive();
}

2、定义readSubject

package Proxy.javaActive;

public class PrinterImpl implements Printer,Email{
    @Override
    public void print() {
        System.out.println("打印机正在打印输出");
    }

    @Override
    public void input() {
        System.out.println("打印机正在接受输入");
    }

    @Override
    public void send() {
        System.out.println("通过打印机发送邮件");
    }

    @Override
    public void receive() {
        System.out.println("通过打印机接收邮件");
    }
}

3、定义动态代理

package Proxy.javaActive;

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

/**
 * 定义java动态代理
 */
public class ActiveProxy {
    //定义实际干活者
    Printer printer = null;

    public ActiveProxy(Printer printer) {
        this.printer = printer;
    }

    public Object createProxy(){
        Object o = Proxy.newProxyInstance(ActiveProxy.class.getClassLoader(), printer.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(method.getName().equals("input")){
                    Object invoke = method.invoke(printer, args);
                    return invoke;
                }else {
                    System.out.println("除了input方法外,其他方法都需要前置处理");
                    Object invoke = method.invoke(printer, args);
                    //通过反射调用对象的方法,参数是对象的实例,以及传入方法的参数
                    //还可以调用proxy代理里面的一些方法,这样就不用重复写业务逻辑了
                    return invoke;
                }
            }
        });
        return o;
    }
}

4、动态代理工厂

package Proxy.javaActive;

public class ActiveFactory {
    public static Object getInstance(){
        return new ActiveProxy(new PrinterImpl()).createProxy();
    }
}

5、客户端

package Proxy.javaActive;

public class Client {
    public static void main(String[] args) {
        //获取Printer的动态代理
        Printer instance = (Printer) ActiveFactory.getInstance();
        instance.print();
        instance.input();

        //获取Email的动态dialing
        Email email = (Email) ActiveFactory.getInstance();
        email.send();
        email.receive();
    }
}

CGLIB动态代理

cglib动态代理基于继承实现,无论被代理者是否实现了接口,其中的方法都可以代理
spring AOP的代理可以使用java动态代理,也可以使用CGLIB动态代理

    package cn.ruanwenfu.proxy;

    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;

    import java.lang.reflect.Method;

    public class CGLibProxy {
        private static FBB fbb = new FBB();
        private static Star getProxy(){
            //获取增强器
            Enhancer enhancer = new Enhancer();
            //可以设置代理的接口,也可以不设置,反正不是基于接口实现
            enhancer.setInterfaces(FBB.class.getInterfaces());
            //设定父类为被代理者
            enhancer.setSuperclass(FBB.class);
            //设置回调函数,也就是方法作为参数传入,代理对象的所有方法都会走这个回调
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    if("eat".equals(method.getName())){
                        System.out.println("方法停用");
                        return null;
                    }else{
                        System.out.println("权限检查");
                        Object invoke = method.invoke(fbb, args);
                        return invoke;
                    }
                }
            });
            return (Star)enhancer.create();
        }

        public static void main(String[] args) {
            Star proxy = CGLibProxy.getProxy();
            proxy.sing();
            proxy.eat();
        }
    }
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值