Java动态代理之拦截器的应用

 更新时间:2019年01月16日 09:21:40   作者:Haozz_1994  
今天小编就为大家分享一篇关于Java动态代理之拦截器的应用,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

由于动态代理一般都比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法、含义和作用即可,无须知道动态代理是怎么实现的。用JDK动态代理来实现一个拦截器的逻辑,为此先定义拦截器接口Interceptor,如下所示:

/**
 * @Auther: haozz
 * @Date: 2018/5/27 22:15
 * @Description:拦截器接口
 **/
public interface Interceptor {
  boolean before(Object proxy, Object target, Method method,Object[] args);
  void around(Object proxy,Object target,Method method,Object[] args);
  void after(Object proxy,Object target,Method method,Object[] args);
}

这里定义了3个方法,before、around、after方法,分别给予这些方法如下逻辑定义:

  1. 3个方法的参数为:proxy代理对象、target真实对象、method方法、args运行方法参数;
  2. before方法返回boolean值,它在真实对象前调用。当返回为true时,则反射真实对象的方法;当返回为false时,则调用around方法;
  3. 在before方法返回为false的情况下,调用around方法
  4. 在反射真实对象方法或者around方法执行之后,调用after方法

实现这个Interceptor的实现类——MyInterceptor,如下:

/**
 * @Auther: haozz
 * @Date: 2018/5/27 22:48
 * @Description:MyInterceptor
 **/
public class MyInterceptor implements Interceptor{
  @Override
  public boolean before(Object proxy, Object target, Method method, Object[] args) {
    System.out.println("反射方法前逻辑");
    return false;//不反射被代理对象原有方法
  }
  @Override
  public void around(Object proxy, Object target, Method method, Object[] args) {
    System.out.println("取代了被代理对象的方法");
  }
  @Override
  public void after(Object proxy, Object target, Method method, Object[] args) {
    System.out.println("反射方法后逻辑");
  }
}

它实现了所有Interceptor接口的方法,使用JDK动态代理,就可以去实现这些方法在适当时的调用逻辑了。以上一篇(Java设计模式之动态代理)中的接口和实现类为例,在JDK动态代理中使用拦截器,如下所示:

/**
 * @Auther: haozz
 * @Date: 2018/5/27 22:30
 * @Description:
 **/
public class InterceptorJdkProxy implements InvocationHandler {
  private Object target;//真实对象
  private String interceptorClass = null;//拦截器全限定名
  public InterceptorJdkProxy(Object target,String interceptorClass){
    this.target = target;
    this.interceptorClass = interceptorClass;
  }
  public static Object bind(Object target,String interceptorClass){
    //取得代理对象
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        new InterceptorJdkProxy(target,interceptorClass));
  }
  @Override
  /**
   * Description:通过代理对象调用方法,首先进入这个方法
   * @auther: haozz
   * @param: proxy 代理对象
   * @param: method 被调用方法
   * @param: args 方法的参数
   * @return: java.lang.Object
   * @date: 2018/5/27 23:00
   **/
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if(interceptorClass == null){
      //没有设置拦截器则直接反射原有方法
      return method.invoke(target,args);
    }
    Object result = null;
    //通过反射生成拦截器
    Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
    //调用前置方法
    if(interceptor.before(proxy,target,method,args)){
      //反射原有对象方法
      result = method.invoke(target,args);
    }else{//返回false执行around方法
      interceptor.around(proxy,target,method,args);
    }
    //调用后置方法
    interceptor.after(proxy,target,method,args);
    return result;
  }
}

这里有两个属性,一个是target,它是真实对象;另一个是字符串interceptorClass,它是一个拦截器的全限定名。解释以下这段代码的执行步骤:

        第1步,在bind方法中用JDK动态代理绑定了一个对象,然后返回代理对象;

        第2步,如果没有设置拦截器,则直接反射真实对象的方法,然后结束,否则进行第3步;

        第3步,通过反射生成拦截器,并准备使用它;

        第4步,调用拦截器的before方法,如果返回为true,反射原来的方法;否则运行拦截器的around方法;

        第5步,调用拦截器的after方法;

        第6步,返回结果。

  • 开发者只要知道拦截器的作用就可以编写拦截器了,编写完后可以设置拦截器,这样就完成了任务,所以对于开发者而言相对简单了
  • 设计者可能是精通Java的开发人员,他来完成动态代理的逻辑
  • 设计者只会把拦截器接口露给开发者使用,让动态代理的逻辑在开发者的视野中“消失”

拦截器可以进一步简化动态代理的使用方法,使程序变得更简单,用如下的测试类测试一下:

public class Mytest {
  public static void main(String []args){
    HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.csdn.blog.interceptor.MyInterceptor");
    proxy1.sayHelloWorld();
  }
}

运行这段代码,得到以下结果:

反射方法前逻辑
取代了被代理对象的方法
反射方法后逻辑

显然,拦截器已经生效。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • java实现桌面右下角弹窗效果

    java实现桌面右下角弹窗效果

    这篇文章主要为大家详细介绍了java实现桌面右下角弹窗效果,模仿类似于qq消息弹窗,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • Java Runtime类详解_动力节点Java学院整理

    Java Runtime类详解_动力节点Java学院整理

    Runtime类封装了运行时的环境。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。下面通过本文给大家分享Java Runtime类详解,需要的朋友参考下吧
    2017-04-04
  • 使用synchronized实现一个Lock代码详解

    使用synchronized实现一个Lock代码详解

    这篇文章主要介绍了使用synchronized实现一个Lock代码详解,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • Java将byte[]转图片存储到本地的案例

    Java将byte[]转图片存储到本地的案例

    这篇文章主要介绍了Java将byte[]转图片存储到本地的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • Mybatis枚举类型转换源码分析

    Mybatis枚举类型转换源码分析

    在Mybatis的TypeHandlerRegistry中,添加了常用的类转换器,其中默认的枚举类型转换器是EnumTypeHandler,这篇文章主要介绍了Mybatis枚举类型转换源码分析,需要的朋友可以参考下
    2024-05-05
  • 基于jQuery获取table数据发送到后端

    基于jQuery获取table数据发送到后端

    这篇文章主要介绍了基于jQuery获取table数据发送到后端,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • java栈实现二叉树的非递归遍历的示例代码

    java栈实现二叉树的非递归遍历的示例代码

    这篇文章主要介绍了java栈实现二叉树的非递归遍历,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Mybatis中自定义TypeHandler处理枚举详解

    Mybatis中自定义TypeHandler处理枚举详解

    本文主要介绍了Mybatis中自定义TypeHandler处理枚举的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • mybatis 事务回滚配置操作

    mybatis 事务回滚配置操作

    这篇文章主要介绍了mybatis 事务回滚配置操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • SpringBoot集成RocketMQ的使用示例

    SpringBoot集成RocketMQ的使用示例

    RocketMQ是阿里巴巴开源的一款消息中间件,性能优秀,功能齐全,被广泛应用在各种业务场景,本文就来介绍一下SpringBoot集成RocketMQ的使用示例,感兴趣的可以了解一下
    2023-11-11

最新评论