设计模式之代理模式

代理模式

这里主要是对代理模式中的 JDK 动态代理CGLIB 代理 以代码的形式做简单的介绍

1. JDK 动态代理

代理对象和目标对象必须实现相同的接口

使用 Proxy 类提供了为对象产生代理对象的方法

public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

  1. ClassLoader loader:和目标对象相同的类加载器;

  2. Class[] interfaces:代理类需要实现的接口;

    也可以直接使用 类.getClass().getInterfaces() 直接获取需要被代理类所实现的接口;

  3. InvocationHandler h:用于指定代理类需要如何去代理(代理要做的事情)。

实现步骤:

1、创建接口、实现类

public interface DeptService {
  // 查找所有部门记录
  void findAllDept();
}
public class DeptServiceImpl implements DeptService {
  @Override
  public void findAllDept(Dept dept) {
    ThreadUtil.sleep(150); // 线程睡眠,防止代码执行过快
    System.out.println("查找所有部门记录");
  }
}

2、创建 JDK 动态代理对象

// JDK 动态代理
@Slf4j
public class JdkProxyFactory {
  /**
   * 创建代理对象
   *
   * @return:
   * @param: target 目标对象
   */
  public static DeptService createProxy(DeptService target) {
    /*
	 * newProxyInstance 参数说明:
	 *     ClassLoader loader: 类加载器
	 *     Class[] interfaces: 接口数组
	 *     InvocationHandler h: 调用处理器
	 */
    Object proxyInstance = Proxy.newProxyInstance(
      target.getClass().getClassLoader(),
      target.getClass().getInterfaces(),
      new InvocationHandler() {
        /**
		 * 调用处理器的 invoke 方法,在调用目标对象的方法时,会调用该方法
		 *
		 * @return:
		 * @param: proxy 代理类对象
		 * @param: method 被代理类中的方法
		 * @param: args 被代理类中的方法的参数
		 */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          // 去除 toString 方法的调用带来的影响
          if ("toString".equals(method.getName())) { return null; }

          // 代理对象要实现的增强功能
          long begin = System.currentTimeMillis();
          Object result = method.invoke(target, args); // 执行目标方法(反射技术)
          long end = System.currentTimeMillis();
          log.info("执行耗时:{}", (end - begin));
          return result;
        }
      }
    );

    return (DeptService) proxyInstance;
  }
}

3、测试

public static void main(String[] args) {
  DeptService target = new DeptServiceImpl();

  // 创建代理对象
  DeptService proxy = JdkProxyFactory.createProxy(target);

  // 让代理对象调用方法
  proxy.findAllDept();
}

注意:被动态代理的对象必须要有实现的接口。

2. Cglib 动态代理

代理对象成为目标对象的子类对象

实现步骤:

1、创建类

public class DeptServiceImpl {
  public void findAllDept(Dept dept) {
    ThreadUtil.sleep(150);
    System.out.println("查找所有部门记录");
  }
}

2、创建 Cglib 代理对象

// Cglib 动态代理
@Slf4j
public class CglibProxyFactory {

  /**
   * 创建代理对象
   *
   * @return:
   * @param: target 目标对象
   */
  public static DeptServiceImpl2 createProxy(DeptServiceImpl2 target) {
    /*
	 * Enhancer.create 方法:自动生成代理对象的子类
	 *     Class type:获取目标对象的类类型
	 *     Callback callback:回调对象,用于拦截目标对象的方法调用并进行增强处理
	 */
    return (DeptServiceImpl2) Enhancer.create(
      target.getClass(),
      new MethodInterceptor() {
        /**
		 * intercept 方法是 MethodInterceptor 接口的唯一方法,
		 *
		 * @return:
		 * @param: obj 被拦截的对象
		 * @param: method 被拦截的方法
		 * @param: args 方法的参数
		 */
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
          // 去除 toString 方法的调用
          if ("toString".equals(method.getName())) {
            return null;
          }

          // 代理对象要实现的增强功能
          long begin = System.currentTimeMillis();
          Object result = method.invoke(target, args); // 执行目标方法(反射技术)
          long end = System.currentTimeMillis();
          log.info("执行耗时:{}", (end - begin));
          return result;
        }
      }
    );
  }
}

3、测试

public static void main(String[] args) {
  DeptServiceImpl2 proxy = CglibProxyFactory.createProxy(new DeptServiceImpl2());
  proxy.findAllDept();
}

你可能感兴趣的:(设计模式,代理模式)