代理模式
静态代理
【角色分析】
- 抽象角色:一般会使用【接口/抽象类】解决
 
- 真实角色:被代理角色
 
- 代理角色:代理真实角色,代理后一般会做一些附属操作
 
- 客户:访问代理对象的人
 
【代码步骤】
- 接口
 
package cn.iris.demo01;
/**
 * @author Iris 2021/8/12
 */
// 租房
public interface Rent {
    public void rent();
}
- 真实角色
 
package cn.iris.demo01;
/**
 * @author Iris 2021/8/12
 */
// 房东
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房子...");
    }
}
- 代理角色
 
package cn.iris.demo01;
/**
 * @author Iris 2021/8/12
 */
public class Proxy implements Rent{
    private Host host;
    public Proxy() {
    }
    public Proxy(Host host) {
        this.host = host;
    }
    @Override
    public void rent() {
        visitHouse();
        fare();
        sign();
        host.rent();
    }
    /**
     * 看房
     */
    public void visitHouse() {
        System.out.println("中介带你看房...");
    }
    /**
     * 收中介费
     */
    public void fare() {
        System.out.println("中介收你钱...");
    }
    /**
     * 签合同
     */
    public void sign() {
        System.out.println("中介和你签租赁合同...");
    }
}
- 客户端访问代理角色
 
package cn.iris.demo01;
/**
 * @author Iris 2021/8/12
 */
public class Client {
    public static void main(String[] args) {
        // 房东:想租房子
        Host host = new Host();
        // 代理:中介帮房东租房子,同时增加附属操作
        Proxy proxy = new Proxy(host);
        // 用户:不用找房东,直接接触中介租房子
        proxy.rent();
    }
}

【代理模式的好处】
- 使真实角色的操作更加纯粹,不用关注一些公共业务
 
- 公共业务交予代理角色负责,实现了业务分工
 
- 公共业务扩展时,方便集中管理
 
- 在项目中可避免对原业务代码进行修改而导致项目崩溃【避免了‘刨祖坟’(狗头)】
 
【缺点】
- 一个真实角色会产生一个代理角色,多个真实角色会产生大量代码,降低开发效率
 
动态代理
- 动态代理与静态代理中的角色相同
 
- 动态代理的代理类动态生成
 
- 动态代理分为两类:基于接口的动态代理,基于类的动态代理
- 基于接口的动态代理---JDK动态代理
 
- 基于类的动态代理---cglib
 
- Java字节码实现:javassist(JBoss服务器)
需要了解两个了:Proxy,InvocationHandler(调用处理程序) 
 
【代码实现】
package cn.iris.demo02;
/**
 * @author Iris 2021/8/12
 */
public interface UserService {
    void add();
    void del();
    void update();
    void query();
}
package cn.iris.demo02;
/**
 * @author Iris 2021/8/12
 */
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加一个用户");
    }
    @Override
    public void del() {
        System.out.println("删除一个用户");
    }
    @Override
    public void update() {
        System.out.println("更新一个用户");
    }
    @Override
    public void query() {
        System.out.println("查询一个用户");
    }
}
package cn.iris.demo04;
import cn.iris.demo03.Rent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 使用该类动态生成代理类
 * @author Iris 2021/8/12
 */
public class ProxyInvocationHandler implements InvocationHandler {
    /**
     * 被代理接口
     */
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    /**
     * 生成得到代理类
     * @return
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(
                this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this);
    }
    /**
     * 处理代理实例并返回结果
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 动态代理本质:使用【反射机制】实现
        log(method.getName());
        Object res = method.invoke(target, args);
        return res;
    }
    public void log(String msg) {
        System.out.println("使用了"+msg+"方法");
    }
}
package cn.iris.demo04;
import cn.iris.demo02.UserService;
import cn.iris.demo02.UserServiceImpl;
/**
 * @author Iris 2021/8/12
 */
public class Client {
    public static void main(String[] args) {
        // 真实角色
        UserServiceImpl userService = new UserServiceImpl();
        // 代理角色(不存在)
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        // 设置要代理的对象
        pih.setTarget(userService);
        // 动态生成代理类
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
        proxy.del();
        proxy.update();
        proxy.query();
    }
}
【动态代理的好处】
- 静态代理的所有好处
 
- 一个动态代理类代理的是一个接口,即是对应的一类业务
 
- 一个动态代理类可以代理多个类,只要实现了同一个接口