设计模式(2)代理模式

一.什么是代理模式?

代理就是在不修改被代理对象的前提下,扩展被代理对象的功能

二.代理模式有哪些分类?

静态代理:程序运行前就已经存在代理类的字节码文件,代理类和目标类的关系就已经确定
动态代理:程序在运行时通过反射机制动态创建(jdk代理,cglib代理)

三.静态代理模式的实现

静态代理是通过代理对象与目标对象实现相同的接口,然后在代理对象中调用目标对象中的方法实现的

1.接口

public interface RentHouse {
    void rent();
}

2.目标对象

public class FindHouse implements RentHouse {
    @Override
    public void rent() {
        System.out.println("我要租房子!");
    }
}

3.代理对象

public class RentProxy implements RentHouse {
    private RentHouse rentHouse;
    public RentProxy(RentHouse rentHouse){
        this.rentHouse = rentHouse;
    }
    @Override
    public void rent() {
        System.out.println("帮你找房子");
        rentHouse.rent();
        System.out.println("帮你搬家");
    }
}

4.测试类

public class Test {
    public static void main(String[] args) {
        FindHouse findHouse = new FindHouse();
        RentProxy proxy = new RentProxy(findHouse);
        proxy.rent();
    }
}

四.动态代理之jdk代理

不需要我们手动的创建代理对象,代理对象的生成,是依靠JDK的API(java.lang.reflect.Proxy),动态的在内存中构建代理对象。

1.定义接口

public interface Person {
    //上交班费
    void giveMoney();
}

2.目标对象实现接口

public class Student implements Person {
    private String name;
    public Student(String name) {
        this.name = name;
    }

    @Override
    public void giveMoney() {
        try {
            //假设数钱花了一秒时间
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + "上交班费50元");
    }
}

3.代理类

public class StuInvocationHandler implements InvocationHandler {
    //invocationHandler持有的被代理对象
    T target;

    public StuInvocationHandler(T target) {
        this.target = target;

    }
    //绑定一个委托对象并返回一个代理类
    public Object bind(T target) {
        this.target = target;
        //取得代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
        //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
    }


    /**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");

        //代理过程中插入监测方法,计算该方法耗时
        MonitorUtil.start();
        Object result = method.invoke(target, args);
        MonitorUtil.finish(method.getName());
        return result;
    }
}

4.代理类中用到的记时工具

public class MonitorUtil {

    private static ThreadLocal tl = new ThreadLocal<>();

    public static void start() {
        tl.set(System.currentTimeMillis());
    }

    //结束时打印耗时
    public static void finish(String methodName) {
        long finishTime = System.currentTimeMillis();
        System.out.println(methodName + "方法耗时" + (finishTime - tl.get()) + "ms");
    }
}

5.执行目标对象时动态的调用代理方法

public class ProxyTest {
    public static void main(String[] args) {

        //创建一个实例对象,这个对象是被代理的对象
        Person zhangsan = new Student("张三");

        //创建一个与代理对象相关联的InvocationHandler
        InvocationHandler stuHandler = new StuInvocationHandler(zhangsan);

        //创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
        Person stuProxy = (Person) ((StuInvocationHandler) stuHandler).bind(zhangsan);

        //代理执行上交班费的方法
        stuProxy.giveMoney();
    }
}

五.cglib代理

CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:

1.目标对象

public class service {  
    public String services(){  
        return "My name is JarremDon";  
    }  
}  

2.代理对象

import java.lang.reflect.Method;  
import net.sf.cglib.proxy.Enhancer;  
import net.sf.cglib.proxy.MethodInterceptor;  
import net.sf.cglib.proxy.MethodProxy;  
public class CglibProxy implements MethodInterceptor {  
    //需要代理的原始类  
    public Object object;  
    public CglibProxy(Object object){  
        this.object=object;  
    }  
    public Object Proxy(){  
        //创建加强器  
        Enhancer enhancer=new Enhancer();  
        //设置需要加强的类  
        enhancer.setSuperclass(object.getClass());  
        //设置回调  
        enhancer.setCallback(this);  
        enhancer.setClassLoader(object.getClass().getClassLoader());  
        return enhancer.create();  
    }  
    @Override  
    public Object intercept(Object arg0, Method arg1, Object[] arg2,  
            MethodProxy arg3) throws Throwable {  
        //这里实现加强  
         Object invoke=arg3.invoke(object, arg2);  
        return invoke.toString().toUpperCase();  
    }  
}  

3.测试类

public class MyTest {  
    public  static  void main(String args[]){  
        service s=new service();  
        CglibProxy proxy=new CglibProxy(s);  
        service s1=(service) proxy.Proxy();  
        System.out.println(s1.services());  
    }  
}  

你可能感兴趣的:(动态代理)