代理模式

武培轩 2020年02月06日 76次浏览

模式定义

给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用

为什么使用代理

在不改变目标对象方法的情况下对方法进行增强

代理模式实例

静态代理

先创建一个用户接口(UserInterface),声明一个方法

public interface UserInterface {

    void service(String s);
}

创建实现类(UserImpl)

public class UserImpl implements UserInterface {

    @Override
    public void service(String s) {
        System.out.println("我是" + s);
    }
}

创建代理对象类(UserProxy),通过代理类创建实现类实例并访问其方法

public class UserProxy implements UserInterface {

    private UserInterface user;

    public UserProxy(UserImpl user) {
        this.user = user;
    }

    @Override
    public void service(String s) {
        System.out.println("检查身份");
        user.service(s);
        System.out.println("请进门");
    }
}

客户端调用

public class ProxyTest {
    public static void main(String[] args) {
        UserImpl user = new UserImpl();
        UserProxy proxy = new UserProxy(user);
        proxy.service("wupx");
    }
}

输出结果

检查身份
我是wupx
请进门

动态代理

先创建一个User接口

public interface User {

    void code();

    void sleep();
}

创建User的实现类(UserImpl)

public class UserImpl implements User {
    @Override
    public void code() {
        System.out.println("开始敲代码");
    }

    @Override
    public void sleep() {
        System.out.println("开始睡觉");
    }
}

再创建一个代理类(UserImpProxy)

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

public class UserImpProxy implements InvocationHandler {

    private User user;

    public UserImpProxy(User user) {
        this.user = user;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Object result;
        if ("code".equals(methodName)) {
            System.out.println("讨论需求");
            result = method.invoke(user, args);
            System.out.println("提测");
        } else if ("sleep".equals(methodName)) {
            System.out.println("洗澡");
            result = method.invoke(user, args);
        } else {
            result = method.invoke(user, args);
        }
        return result;
    }
}

去测试动态代理

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

public class TestProxy {
    public static void main(String[] args) {
        UserImpl user = new UserImpl();
        InvocationHandler userProxyHandler = new UserImpProxy(user);
        User userProxy = (User) Proxy.newProxyInstance(user.getClass().getClassLoader(),
                user.getClass().getInterfaces(), userProxyHandler);
        userProxy.code();
        userProxy.sleep();
    }
}

运行结果

讨论需求
开始敲代码
提测
洗澡
开始睡觉

总结

使用Java动态代理的两个重要步骤

  1. 通过实现 InvocationHandler 接口创建自己的调用处理器;
  2. 通过为Proxy类的newProxyInstance方法指定代理类的ClassLoader 对象和代理要实现的interface以及调用处理器InvocationHandler对象来创建动态代理类的对象;