大话设计模式之代理模式

代理模式

  可以理解为一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

通过代码分析理解 

//买房动作
public interface BuyHouse {
    void buyHouse();
}

//客户直接买房
public class BuyHouseImpl implements BuyHouse {
    @Override
    public void buyHouse() {
        System.out.println("我要买房子");
    }
}

//通过代理(中介)买房
public class BuyHouseProxy implements BuyHouse {
    BuyHouse buyHouse;

    public BuyHouseProxy(BuyHouse buyHouse){
        this.buyHouse=buyHouse;
    }

    @Override
    public void buyHouse() {
        System.out.println("买房前准备");
        buyHouse.buyHouse();
        System.out.println("买房后装修");
    }
}

main测试

public class MianTest {

    public static void main(String[] args){
        BuyHouse buyHouse = new BuyHouseImpl();
        BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
        buyHouseProxy.buyHouse();
    }

}

//执行结果
买房前准备
我要买房子
买房后装修

代理模式的应用场景:

1、远程代理,也就是为一个对象在不同的地址空间提供局部代表。

2、虚拟代理,是根据需要创建开销很大的对象。通过他来存放实例化需要很长时间的真是对象。

3、安全代理,用来控制真实对象访问时的权限。

4、智能引用,是指当调用真实对象时,代理处理另外一些事。

 

2018/9/10修改

上述代理模式是基于静态代理的一种实现,那么下面来讲解基于jdk的动态代理

动态代理实现之jdk动态代理

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

实现原理:采用反射技术

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

代码实现(还是基于买房示例,现在我们只需创建一个动态代理类即可)

package com.chenpt.designModel.proxyFactory;

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

/**
 * @Author: chen
 * @Description: jdk的动态代理
 * @Date: created in 2018/9/10
 * @Modified By:
 */
public class MyProxy implements InvocationHandler {

    public Object target;

    MyProxy(Object target){
        this.target = target;
    }

    /**
     * @param proxy  需要代理的真实类
     * @param method 真实类的方法
     * @param args   方法所需参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("++++++before " + method.getName() + "++++++");
        Object result = method.invoke(target,args);
        System.out.println("++++++after " + method.getName() + "++++++");
        return result;
    }
}

  客户端

package com.chenpt.designModel.proxyFactory;
import java.lang.reflect.Proxy;

/**
 * @Author: chenpengtao
 * @Description:
 * @Date: created in 2018/7/24
 * @Modified By:
 */
public class MianTest {


    public static void main(String[] args){
        BuyHouse buyHouse2 = new BuyHouseImpl2();

        MyProxy myProxy = new MyProxy(buyHouse2);
        try {
            BuyHouse subject = (BuyHouse) Proxy.newProxyInstance(myProxy.getClass().getClassLoader(),buyHouse2.getClass().getInterfaces(),myProxy);
            subject.buyHouse();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

    }

}
//执行结果
++++++before buyHouse++++++
我要买房子2
++++++after buyHouse++++++

 

动态代理实现之cglib代理

  cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。不能对final修饰的类进行代理。 

实现原理:采用字节码(asm)技术

还以买房为例,现在只需实现cglib代理类即可

package com.chenpt.designModel.proxyFactory;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.annotation.Primary;

import java.lang.reflect.Method;

/**
 * @Author: chen
 * @Description: 基于cglib的动态代理
 * @Date: created in 2018/9/10
 * @Modified By:
 */
public class MyCglib implements MethodInterceptor{

    private Object target;

    //相当于JDK动态代理中的绑定
    public Object getInstance(Object target) {
        this.target = target;  //给业务对象赋值
        Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
        enhancer.setSuperclass(this.target.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(this);
        // 创建动态代理类对象并返回
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("预处理——————");
        methodProxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
        System.out.println("调用后操作——————");
        return null;
    }
}

  客户端

package com.chenpt.designModel.proxyFactory;
import java.lang.reflect.Proxy;

/**
 * @Author: chenpengtao
 * @Description:
 * @Date: created in 2018/7/24
 * @Modified By:
 */
public class MianTest {


    public static void main(String[] args){
        BuyHouse buyHouse2 = new BuyHouseImpl2();

        MyCglib myCglib = new MyCglib();

        buyHouse2 = (BuyHouse) myCglib.getInstance(buyHouse2);
        buyHouse2.buyHouse();
    }

}
//执行结果
预处理——————
我要买房子2
调用后操作——————

  

 

posted @ 2018-07-25 11:49  不二尘  阅读(175)  评论(0编辑  收藏  举报