设计模式之代理模式

设计模式系列文章:

  1、设计模式之工厂模式
  2、设计模式之单例模式
  3、设计模式之代理模式
  4、设计模式之外观模式(即门面模式)
  5、设计模式之策略模式
  6、设计模式之责任链模式
  7、设计模式之观察者模式
  8、设计模式之建造者模式

设计模式是一套反复使用的、多数人知晓的、经过分类编目的、代码设计经验总结。使用设计模式为了提高代码的可重用性,让代码更容易被他人理解,保证代码的可靠性。

代理模式:
For example :比如某歌星知名度非常高,很多单位都想请他去唱歌,但是呢,总不能他又要唱歌又要给自己接活吧,一般的都会雇佣一个经济人,这里的经济人他就是一个代理。如果有人想请该歌星去唱歌,那么需要直接联系的人是歌星的经济人,而不是直接找歌星,找到该经纪人以后谈好价钱,然后歌星再来唱歌,唱完歌以后,可能还需要与经纪人之间进行一些后续事物的处理。

一、代理模式的定义

为其他对象提供一种代理以控制对这个对象的访问
如果业务需求增加,则需要改动大量的代码,而使用代理对象起到中介作用,可以增加额外的服务

二、静态代理

1、创建接口Person以及被被代理类Singer
2、创建代理类Agent,并在Agent中聚合Singer

在我们使用静态代理的时候,每一个代理类只能为一个接口提供服务,这这样一来在程序开发中会产生过多的代理,而且所有的代理操作除了调用的方法不一样之外,其他的操作都是相同的,这样就会造成过多的重复代码;

   为了解决上述问题,我们使用一个代理类来完成所有的代理功能,而这就需要引入动态代理;

三、JDK动态代理

相比于Cjlib动态代理,jdk动态代理是针对实现了接口的类进行代理,而Cglib动态代理是针对类进行代理
Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
(1) java.lang.reflect.InvocationHandler:该接口中仅定义了一个方法
public Object invoke(Object obj,Method method,Object[] args)
参数:
obj一般是指代理类;
method是被代理的方法;
args为该方法的参数数组。
这个抽象方法在代理类中动态实现。
(2)java.lang.reflect.Proxy:该类即为动态代理类
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,
InvocationHandler h)
返回代理类的一个实例,返回后的代理类可以当做被代理类使用
(可使用被代理类的在接口中声明过的方法)
jdk动态代理的使用步骤:
1.创建被代理的类以及接口
2.创建一个实现InvocationHandler接口的类,它必须实现invoke方法
3.调用Proxy的静态方法,创建一个代理类
newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
4.通过代理调用方法
代码示例:

package com.tong.Proxy;
/**
* @describe 抽象接口
* @author tong
* @version 1.0 2017-11-11
*/
public interface Person {
    public void sing();
}
package com.tong.Proxy;
/**
* @describe Person接口的具体实现 歌手Singer
* @author tong
* @version 1.0 2017-11-11
*/
public class  Singer implements Person {
    @Override
    public void sing() {
        System.out.println("********************歌手:我正在唱歌***********************");
    }
}
package com.tong.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @describe 使用JDK动态代理
 * @author tong
 * @version 1.0 2017-11-11
 */
public class AgencyHandler implements InvocationHandler {
    private Object target;
    public AgencyHandler(Object target) {
        super();
        this.target = target;
    }
    /**
     * 参数:
     * proxy 被代理对象
     * method 被代理对象方法
     * args 方法的参数
     * 返回值:
     * Object 方法的返回值
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("******************演唱会以前:经纪人与合作商谈好价钱并签订合同***********************");
        method.invoke(target);
        System.out.println("******************演唱会以后:合作商按照合同把钱支付给经纪人***********************");
        return null;
    }

}
package com.tong.Proxy;

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

public class Test {
    public static void main(String[] args){
        Singer singer = new Singer();
        Class cls = singer.getClass();
        InvocationHandler h = new AgencyHandler(singer);
        // 使用Proxy类newProxyInstance方法动态创建代理类
        /**
         * loader 类加载器
         * interfaces 实现接口
         * h InvocationHandler
         */
        //输出生成的代理类的类名,默认类名一般是$Proxy0,$Proxy1、$Proxy2等等
        System.out.println(Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h).getClass());

        Person p = (Person) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
        p.sing();

    }

}

运行结果:

class com.sun.proxy.$Proxy0
******************演唱会以前:经纪人与合作商谈好价钱并签订合同***********************
********************歌手:我正在唱歌***********************
******************演唱会以后:合作商按照合同把钱支付给经纪人***********************

小结:
使用JDK动态代理有一个问题:被代理的类必须实现接口,未实现接口则没办法完成动态代理。

如果项目中有些类没有实现接口,则不应该为了实现动态代理而刻意去抽出一些没有实例意义的接口,通过cglib可以解决该问题。

三、Cglib动态代理

CGLIB(Code Generation Library)是一个开源项目,是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口,通俗说cglib可以在运行时动态生成字节码。

使用cglib完成动态代理,大概的原理是:cglib继承被代理的类,重写方法,织入通知,动态生成字节码并运行,因为是继承所以final类是没有办法动态代理的。具体实现如下:
1、配置maven,安装Cglib
2、实现 MethodInterceptor方法代理接口,创建代理类
3、最后通过动态代理类对象进行方法调用。

小结:
使用cglib可以实现动态代理,即使被代理的类没有实现接口,但被代理的类必须不是final类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值