zoukankan      html  css  js  c++  java
  • Java动态代理

    1.动态代理概念

      动态代理是程序在运行过程中自动创建一个代理对象代替被代理的对象去执行相应的操作。在Java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口,另一个是Proxy类,这两个是实现动态代理必须用到的。

    2.动态代理的实现

    (1)创建一个类实现InvocationHandler接口,并实现invoke方法。每个动态代理类都必须实现InvocationHandler接口,并在invoke方法中调用被代理的真实对象的方法及在其前后添加相应的方法和逻辑实现代理的功能。

    (2)使用Proxy类的newProxyInstance方法创建一个代理对象,并关联到一个InvocationHandler对象

    实现(1)、(2)步之后,当我们调用代理对象的方法时,该方法调用就会被转化为代理对象关联到的InvocationHandler对象的invoke方法调用。

    我们首先看一下InvocationHandler接口的invoke方法

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}

    这个方法一共接收3个参数,含义分别为:

    proxy:代理对象

    method:代理对象调用的方法的Method对象

    args:代理对象调用方法时传入的参数

    再看一下Proxy类,Proxy类提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler){}

    这个方法的作用就是创建一个代理对象,并关联一个InvocationHandler对象,其接收的3个参数含义为:

    loader:定义了由哪个ClassLoader来加载创建的代理对象

    interfaces:表示我们将给代理对象提供一组什么接口,如果我们提供了一组接口,那么这个代理对象就宣称实现了该接口(多态),这样我们就能调用这组接口中的方法了

    handler:表示代理对象关联的InvocationHandler对象

    -------------------Talk is cheap,show me the code----------------

    定义一个接口,真实对象和代理对象都实现该接口

    package com.jiangwangxiang.dynamicProxy;

    public interface IService {
      public Object execute();
    }

    真实对象的类

    package com.jiangwangxiang.dynamicProxy;

    public class MajorService implements IService{

      @Override
      public Object execute() {
        System.out.println("主业务执行...");
        return null;
      }
    }

    创建动态代理类

    package com.jiangwangxiang.dynamicProxy;

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

    //创建一个代理类,实现InvocationHandler接口
    public class LogProxy implements InvocationHandler {
      //被代理真实对象
      private MajorService target;

      public LogProxy(MajorService target) {
        this.target = target;
      }

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 被代理的真实对象的方法调用前的方法逻辑
        System.out.println("----主业务执行前处理----");
        // 调用被代理的真实对象的方法
        Object result = target.execute();
        // 被代理的真实对象的方法调用后的方法逻辑
        System.out.println("----主业务执行后处理----");
        // 返回被代理对象的方法返回值,一般代理对象都只在被代理对象的方法执行前后添加一些逻辑,不影响方法执行结果
        return result;
      }

    }

    测试类

    package com.jiangwangxiang.dynamicProxy;

    import java.lang.reflect.Proxy;

    //动态代理测试类
    public class DynamicProxyTest {

      public static void main(String[] args) {
      //创建被代理的真实对象
      MajorService majorService = new MajorService();
      //创建InvocationHandler对象,传入被代理的真实对象
      LogProxy handler = new LogProxy(majorService);
      //创建代理对象,并与InvocationHandler对象关联
      IService serviceProxy = (IService) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
      majorService.getClass().getInterfaces(), handler);
      //调用代理对象的方法,该方法调用将会被转化为代理对象关联的InvocationHandler对象的invoke方法调用
      serviceProxy.execute();
      }

    }

    -------------------------

    输出结果为:

    ----主业务执行前处理----
    主业务执行...
    ----主业务执行后处理----

  • 相关阅读:
    Codeforces 946 A.Partition
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) H.Tree Recovery-完全版线段树(区间更新、区间求和)
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) F.The Biggest Water Problem
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) B.Big Water Problem-完全版线段树(单点更新、区间求和)
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) A.逆序数
    POJ 3368.Frequent values-处理数据+RMQ(ST)
    hdu 3033 I love sneakers! 分组背包
    bzoj 2957: 楼房重建 线段树
    hdu 5925 Coconuts 离散化+dfs
    HDU 5929 Basic Data Structure 模拟
  • 原文地址:https://www.cnblogs.com/jiangwangxiang/p/8475938.html
Copyright © 2011-2022 走看看