设计模式-代理的代码实现与详解

package com.zqh.proxy;

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

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

interface IMessage{//传统代理设计必须有接口
    public void send();
}
class MessageReal implements IMessage{
    @Override
    public void send() {
        System.out.println("消息发送");
    }

}
class MessageProxy implements IMessage{
    private IMessage message;//代理对象,一定是业务接口实例
    public MessageProxy(IMessage message){
        this.message = message;
    }
    public boolean connect(){
        System.out.println("消息代理——连接");
        return true;
    }
    public void close(){
        System.out.println("消息代理——关闭");
    }
    @Override
    public void send() {
        if(this.connect()){
            this.message.send();
            this.close();
        }
    }
}

class ProxyHandler implements InvocationHandler{
    private Object target;//保存真实业务对象
    /**
     * 进行真实业务对象与代理业务对象之间的绑定处理
     * @param target 真实业务对象
     * @return Proxy生成的代理业务对象
     */
    public Object bind(Object target){
        this.target = target;
        /**
         * 对于动态对象的创建是由JVM底层完成的,此时主要依靠的时java.lang.reflect.Proxy程序类,只提供有一个核心方法:
         * 代理对象:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
         InvocationHandler h) throws IllegalArgumentException
         * 		ClassLoader loader:获取当前真实主体类的ClassLoader;
         * 		Class<?>[] interfaces:代理是围绕接口进行的,所以一定要获取真实主题类的接口信息;
         * 		InvocationHandler h:代理处理的方法。
         */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
    public boolean connect(){
        System.out.println("消息代理——连接");
        return true;
    }
    public void close(){
        System.out.println("消息代理——关闭");
    }
    /**
     * public interface InvocationHandler
     * 代理方法调用,代理主题类里面执行的方法最终都是此方法
     * @param proxy 要代理的对象
     * @param method 要执行的接口方法名称
     * @param args 传递的参数
     * @return 某一个方法的返回值
     * @throws Throwable 方法调用时出现的错误继续向上抛出
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行方法:\t"+method);
        Object returnData = null;
        if(this.connect()){
            returnData = method.invoke(this.target, args);
            this.close();
        }
        return returnData;
    }
}
public class ProxyImpl {
    public static void main(String[] args) {
//静态代理设计模式
        System.out.println("-----静态代理设计模式-----");
        /**
         * 核心是有真实业务实现类与代理业务实现类,并且代理类要完成比真实业务更多的处理操作。
         * 传统代理模式的弊端:需要首先定义出核心接口的组成。
         */
        IMessage message = new MessageProxy(new MessageReal());
        message.send();
        /**
         * 客户端的接口与具体的子类产生了耦合问题,最好再引入工厂设计模式进行代理对象的获取。
         * 静态代理设计的特点在于:一个代理类只为一个接口服务
         */
//动态代理设计模式
        System.out.println("-----动态代理设计模式-----");
        /**
         * 不管是动态代理还是静态代理都一定要接收真实业务实现子类对象;
         * 由于动态代理类不再与某一个具体接口进行捆绑,所以应该可以动态获取类的接口信息。
         */
        message = (IMessage) new ProxyHandler().bind(new MessageReal());
        message.send();
        /**
         * 观察系统中提供的Proxy.newProxyInstance()方法会方法该方法会使用大量的底层机制来进行代理对象的动态创建,
         * 所有的代理类是符合所有向相关功能需求的操作功能类,它不再代表具体的接口,这样在处理的时候就必须依赖于类加载器于接口进行代理对象的伪造。
         */

//CGLIB实现代理设计模式
        System.out.println("-----CGLIB实现代理设计模式-----");
        /**
         * 有一部分开发者就认为不应该强迫性的基于接口来实现代理设计,
         * 开发者设计了CGLIB开发包,可以实现基于类的代理设计模式。
         * 1.CGLIB是一个第三方的程序包,导包
         * 2.编写程序类,该类不实现任何接口。
         * 3.利用CGLIB编写代理类,但是这个代理类需要做一个明确,此时相当于使用类的形式实现了代理设计的处理,
         * 		所以该代理设计需要通过CGLIB来生成代理对象。
         * 4.此时如果要想创建代理类对象,则就必须进行一系列的CGLIB处理。
         */
        Message realObject = new Message();//真实主题对象
        Enhancer enhancer = new Enhancer();//负责代理操作的程序类
        enhancer.setSuperclass(realObject.getClass());//假定一个父类
        enhancer.setCallback(new ZQHProxy2(realObject));//设置代理类
        Message proxyObject = (Message) enhancer.create();//创建代理对象
        proxyObject.send();
        //但从正常的设计角度来讲,强烈建议还是基于接口的设计会比较合理。
    }
}

//  👇👇👇CGLIB👇👇👇
class Message {
    public void send() {
        System.out.println("消息发送");
    }

}
class ZQHProxy2 implements MethodInterceptor {//拦截器配置
    private Object target;//保存真实主题对象
    public ZQHProxy2(Object target){
        this.target = target;
    }
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        Object returnData = null;
        if(this.connect()){
            returnData = method.invoke(this.target, args);
            this.close();
        }
        return returnData;
    }
    public boolean connect(){
        System.out.println("CGLIB消息代理——连接");
        return true;
    }
    public void close(){
        System.out.println("CGLIB消息代理——关闭");
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值