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();
  }
}

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

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

显然,拦截器已经生效。

总结

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

(0)

相关推荐

  • Java中的拦截器、过滤器、监听器用法详解

    本文实例讲述了Java中的拦截器.过滤器.监听器用法.分享给大家供大家参考,具体如下: 一.拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方 法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作. 1.Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,

  • 浅析JAVA中过滤器、监听器、拦截器的区别

    1.过滤器:所谓过滤器顾名思义是用来过滤的,在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者struts的action前统一设置字符集,或者去除掉一些非法字符(聊天室经常用到的,一些骂人的话).filter 流程是线性的, url传来之后,检查之后,可保持原来的流程

  • java自定义拦截器用法实例

    本文实例讲述了java自定义拦截器及其用法.分享给大家供大家参考.具体如下: LoginInterceptor.java文件如下: package com.tq365.util; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwo

  • java利用mybatis拦截器统计sql执行时间示例

    可以根据执行时间打印sql语句,打印的sql语句是带参数的,可以拷贝到查询分析器什么的直接运行 复制代码 代码如下: package mybatis; import java.text.DateFormat;import java.util.Date;import java.util.List;import java.util.Locale;import java.util.Properties; import org.apache.ibatis.executor.Executor;import

  • Java的Struts2框架中拦截器使用的实例教程

    1.拦截器小介 拦截器的功能类似于web.xml文件中的Filter,能对用户的请求进行拦截,通过拦截用户的请求来实现对页面的控制.拦截器是在Struts-core-2.2.3.jar中进行配置的,原始的拦截器是在struts-default.xml中配置的,里面封存了拦截器的基本使用方法. Struts2拦截器功能类似于Servlet过滤器.在Action执行execute方法前,Struts2会首先执行struts.xml中引用的拦截器,如果有多个拦截器则会按照上下顺序依次执行,在执行完所有

  • java MyBatis拦截器Inteceptor详细介绍

    有许多java初学者对于MyBatis拦截器Inteceptor不是很了解,在这里我来为各位整理下篇关于java中MyBatis拦截器Inteceptor详解, 本文主要分析MyBatis的插件机制,实际就是Java动态代理实现的责任链模式实现. 根据官方文档.Mybatis只允许拦截以下方法,这个决定写拦截器注解签名参数. 代码如下 Executor (update, query, flushStatements, commit, rollback, getTransaction, close

  • Android 封装Okhttp+Retrofit+RxJava,外加拦截器实例

    1.创建一个接口,用来定义接口使用的 public interface Api { @POST("product/getProductDetail") Observable<Goods_Bean> getGoods(@QueryMap Map<String,String> map); @POST("product/addCart") Observable<Add_Bean> getAdd(@QueryMap Map<Stri

  • 详解java中spring里的三大拦截器

    Filter 新建 TimeFilter @Component public class TimeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("time filter init"); } @Override public void doFilter(ServletRequest s

  • 应用市场中Java拦截器和切面的使用实例详解

    相信大家对拦截器和切面的概念已经不陌生了,本文我们就看一些在应用市场中,拦截器和切面的使用是怎样的. 拦截器的使用:每次接收到某个请求之前,都会调用此拦截器中的方法,其中preHandle方法如果return true,表示继续调用对应的controller,如果return false, public class CheckLoginInterceptor implements HandlerInterceptor { private Logger logger = Logger.getLog

  • 浅析java中 Spring MVC 拦截器作用及其实现

    拦截器的实现 1.编写拦截器类实现HandlerInterceptor接口: 2.将拦截器注册进springmvc框架中: 3.配置拦截器的拦截规则: 其他实现方法 WebRequestInterceptor接口: 与上一个的区别是参数区别和prehandle的方法没有返回值.没有上一个功能全,因此常用第一个. 拦截器的使用场景  处理所有请求共性问题: 1.乱码问题:用request,response参数去设置编码: 2.解决权限验证问题(是否登陆,取session对象查看): 拦截器与过滤器

随机推荐