代理模式

一, 代理模式

(1)定义:

引入一个新的对象,来实现对真实对象的操作或者将新的对象作为真实对象的一个替身,这种实现机制即为代理模式,通过引用代理对象来间接访问一个对象。这就是代理模式的模式动机
                      ——————《设计模式》,清华大学出版社

(2)模式中涉及的角色:

  • 抽象主题角色(Subject)
    1,抽象主题角色声明了真实主题角色和代理主题角色的共同接口。
    2,需要面向抽象主题角色编程。

  • 代理主题角色(Proxy)
    1,代理主题角色包含对于真实主题角色的引用,保证了通过代理主题角色去操作真正的主题角色。
    2,代理主题角色中提供了与真实主题相同的接口,保证可以替代真实主题角色对象。
    3,代理主题角色可以控制真实主题角色的使用和删除。

  • 真实主题角色(RealSubject)
    1,真实的主题角色定义了代理角色所代表的的真实对象。
    2,在真实主题角色中实现了真实的业务操作。
    3,使用方式是客户端通过代理角色操作真实角色,使用真实主题角色中的业务方法。

二,两种代理模式

代理模式分为:

-静态代理:
静态代理在使用的时候,需要定义接口(或父类),被代理的对象和代理对象共同实现接口或者继承父类。

public interface DaoInterface {
    void say();
}
public class RealImpl implements DaoInterface{

    public void say() {
        System.out.println("真实主题角色类……");
    }
}
public class ProxyImpl implements DaoInterface {
    private DaoInterface target;

    public ProxyImpl(DaoInterface target) {
        this.target = target;
    }

    public void say() {
        System.out.println("before……");
        this.target.say();
        System.out.println("After……");
    }
}
public class TestMain {
    public static void main(String[] args) {
        RealImpl real = new RealImpl();//真实对象
        ProxyImpl proxy = new ProxyImpl(real);//代理对象
        proxy.say();//通过代理对象调用真实对象的方法
    }
}

缺点:真实和代理对象对需要实现接口,且代码之间的关系复杂。

-动态代理:
在java中有很多种实现方式,JDK,CGLIB,Javassist,ASM。其中最常用的是JDK和CGLIB的方法。

三,java中动态代理模式的实现

(1)JDK动态代理:

JDK动态代理是java.lang.reflect.*包提供的,需要借助一个接口才能产生代理对象。
接口

public interface DaoInterface {
    public void say();
}

实现类,真实角色,真实对象

public class RealImpl implements DaoInterface {
    public void say() {
        System.out.println("真实角色……");
    }
}

动态代理角色:
首先代理的实现需要继承InvocationHandler接口。
然后实现invoke方法。在invoke方法中你可以调用真实对象的逻辑业务代码。

/**
 * jdk动态代理
 */
public class JDKProxyImpl implements InvocationHandler {
    //用于真实对象
    private Object target = null;
    //建立真实对象和代理对象的关系,并通过此方法返回代理对象
    public Object bind(Object target){
      this.target = target;
      return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    /**
    **代理方法逻辑
    **/
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理类的逻辑方法……");
        System.out.println("真实方法之前的服务……");
         Object object = method.invoke(target,args);
        System.out.println("在调度真实对象之后的服务……");
        return object;
    }
}

bind方法中绑定代理对象和真实对象之间的关系。用target来保存对象,然后通过Proxy提供的newProxyInstance方法进行代理关系的绑定。

  • 这里使用的newProxyInstance方法有三个参数,
    1,target.getClass().getClassLoader():类加载器。
    2,target.getClass().getInterfaces(),把生成动态的代理对象挂到某个接口下。
    3,this表示当前对象,是定义实现方法逻辑的代理类。

  • 在本代理类中还需要实现invoke方法。在invoke中需要实现真实对象的逻辑业务,同时也可以添加上代理对象的方法。
    invoke方法中还存在三个参数:
    1,Object proxy:代理对象,就是bind方法生成的对象。
    2,Method method:当前使用调度的真实对象的方法。
    3,Object[] args:调度方法的参数

  • 特点与缺点:
    十分常用的代理方式。但是需要接口才能实现代理。

2,CGLIB动态代理

1,代码:
(1)真实对象

public class RealObject {
    public void say(){
        System.out.println("我是真实对象的业务逻辑……");
    }

}

(2)代理对象

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    /**
     * 生成CGLIB代理对象
     * @param cls
     * @return
     */
    public Object getProxy(Class cls){
        //使用CGLIB enhancer的增强类对象
        Enhancer enhancer = new Enhancer();
        //设置增强类型
        enhancer.setSuperclass(cls);
        //定义逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
        enhancer.setCallback(this);
        //生成并返回代理对象
        return enhancer.create();
    }

    /**
     * 代理对象的逻辑方法,在这里调用真正对象的逻辑业务方法
     * @param proxy
     * @param method
     * @param objects
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("-----------------------");
        Object result = methodProxy.invokeSuper(proxy,objects);
        System.out.println("------------------------");
        return result;
    }
}

这里需要注意导入CGLIB的对应的包。
getProxy方法中,使用了CGLIB的加强者,Enhancer,通过设置超类方法,在通过设置setback方法设置该代理对象为那个的代理对象。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值