【设计模式】代理模式 ( 动态代理 )(一)

文章目录

一、动态代理使用流程

二、动态代理代码示例

1、订单类

2、Service 接口

3、Service 实现类

4、Service 静态代理类

5、Dao 接口

6、设计模式及其应用场景Dao 实现类

7、Ser存储vice 动态代理类

8、测试类

三、动态代设计模式的6大原则理源码分析

一、动态代理使用流程

动态的代理类使用流程 :

1. 内部持有 目标对象
 2. 创建动态代理类 , 调用 Proxy.newProxyInstance 创建动态代理类
     系统会自动创建一个类 , 该类实现了目标对象的所有接口的所有方法
     最后返回一个该动态代理类的实例对象
 3. 调用动态代理类实例对象的某个接口方法 , 会自动回调 动态代理类的 invoke 函数
         注意 : 被代理的方法必须是 目标对象 的接口中的方法

二、动态代理代码示例

业务场景 : 保存订单信息 , 在 Service 层处理订单保存 , 在 Dao 层将订单存储数据库 ; 使用动态代理设计模式面试题类加强 Servic存储e 层的功能 ;

1、订单类

package proxy;
/**
 * 订单类
 *      存储订单时 , 通过 Service 层通接收 Order 对象进行处理
 */
public class Order {
    /**
     * 订单信息
     */
    private Object orderInfo;
    /**
     * 用户 ID
     */
    private Integer userId;
    public Order(Object orderInfo, Integer userId) {
        this.orderInfo = orderInfo;
        this.userId = userId;
    }
    public Object getOrderInfo() {
        return orderInfo;
    }
    public void setOrderInfo(Object orderInfo) {
        this.orderInfo = orderInfo;
    }
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
}

2、Service 接口

package proxy;
/**
 * 服务接口
 */
public interface IOrderService {
    /**
     * 保存订单
     * @param order 数据库生效行数
     * @return
     */
    int saveOrder(Order order);
}

3、Servic存储器e 实数据库系统工程师现类

package proxy;
public class OrderServiceImpl implements IOrderService {
    private IOrderDao iOrderDao;
    public OrderServiceImpl(IOrderDao iOrderDao) {
        this.iOrderDao = iOrderDao;
    }
    @Override
    public int saveOrder(Order order) {
        System.out.println("Service 层插入 Order 订单信息成功");
        return this.iOrderDao.insert(order);
    }
}

4、Ser设计模式中代理模式分为vice 静态代理类

package proxy;
/**
 * 订单服务静态代理类
 */
public class OrderServiceStaticProxy {
    private IOrderService iOrderService;
    public OrderServiceStaticProxy(IOrderService iOrderService) {
        this.iOrderService = iOrderService;
    }
    public int saveOrder(Order order){
        beforeMethod();
        int result = iOrderService.saveOrder(order);
        afterMethod();
        return result;
    }
    /**
     * 在被代理对象方法之前执行的内容
     */
    private void beforeMethod() {
        System.out.println("静态代理 OrderServiceStaticProxy 执行 saveOrder 之前");
    }
    /**
     * 在被代理对象方法之后执行的内容
     */
    private void afterMethod() {
        System.out.println("静态代理 OrderServiceStaticProxy 执行 saveOrder 之后");
    }
}

5、Dao 接口

package proxy;
/**
 * 数据库接口
 */
public interface IOrderDao {
    /**
     * 向数据库中插入订单信息
     * @param order
     * @return
     */
    int insert(Order order);
}

6、Dao 实现类

package proxy;
public class OrderDaoImpl implements IOrderDao {
    @Override
    public int insert(Order order) {
        System.out.println("Dao 层插入 Order 订单信息成功");
        return 1;
    }
}

7设计模式的6大原则、Service 动态代理类

package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 订单服务动态代理类
 *
 * 动态的代理类使用流程 :
 *      1. 内部持有 目标对象
 *      2. 创建动态代理类 , 调用 Proxy.newProxyInstance 创建动态代理类
 *          系统会自动创建一个类 , 该类实现了目标对象的所有接口的所有方法
 *          最后返回一个该动态代理类的实例对象
 *      3. 调用动态代理类实例对象的某个接口方法 , 会自动回调 动态代理类的 invoke 函数
 *              注意 : 被代理的方法必须是 目标对象 的接口中的方法
 */
public class OrderServiceDynamicProxy implements InvocationHandler {
    private Object target;
    public OrderServiceDynamicProxy(IOrderService iOrderService) {
        this.target = iOrderService;
    }
    /**
     * 绑定方法
     *      将目标对象与动态代理类进行绑定
     */
    public Object bind() {
        // 拿到目标对象的类
        Class clazz = target.getClass();
        // 动态代理类时系统执行的时候自动生成的类 , 该类自动实现了指定的接口
        //      动态代理类会获取目标对象的所有接口 , 并实现所有的接口中的所有的方法
        //      该动态代理类 代理的是 target 的接口的方法 , 即 IOrderService 接口的方法
        //      凡是调用创建的动态代理实例对象中的 IOrderService 接口方法 , 都会触发该类的 invoke 方法
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }
    /**
     * 调用代理类的 IOrderService 接口方法 , 就会自动回调该方法
     *      注意 : 所有的 IOrderService 接口方法 , 都会回调该方法
     *            在回调时 , 需要判定一下 , 是哪个方法回调的 , 过滤掉不需要加强的方法
     *
     * @param proxy 该参数几乎用不到
     * @param method 要被增强的方法对象
     * @param args 要被增强的方法对象的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        beforeMethod();
        // 调用目标对象的 method 方法
        Object object = method.invoke(target, args);
        afterMethod();
        return object;
    }
    /**
     * 在被代理对象方法之前执行的内容
     */
    private void beforeMethod() {
        System.out.println("动态代理 OrderServiceStaticProxy 执行 saveOrder 之前");
    }
    /**
     * 在被代理对象方法之后执行的内容
     */
    private void afterMethod() {
        System.out.println("动态代理 OrderServiceStaticProxy 执行 saveOrder 之后");
    }
}