Java拦截器

JDK动态代理


最近也在疯狂的补基础知识,因此写这篇博客为了方便以后自己查看。

拦截器

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

     import java.lang.reflect.Method;
    
     public interface Interceptor {
         /**
          * 当返回为true时,则反射真实对象的方法;
          * 当返回为false时,则调用around方法。
          * @param proxy 代理对象
          * @param target    真实对象
          * @param method    方法
          * @param args  运行方法参数
          * @return
          */
         public boolean before(Object proxy, Object target, Method method,Object[] args);
    
         /**
          * 在before方法返回为false时,则调用around方法。
          * @param proxy
          * @param target
          * @param method
          * @param args
          * @return
          */
         public void around(Object proxy, Object target,Method method,Object[] args);
    
         /**
          * 在反射真实对象方法或者around方法执行之后,调用after方法
          * @param proxy
          * @param target
          * @param method
          * @param args
          * @return
          */
         public void after(Object proxy, Object target,Method method,Object[] args);
     }
    
  • 创建这个Interceptor的实现类-----MyInterceptor

    package com.yl.interceptor;
    
    import java.lang.reflect.Method;
    
     /**
      * 拦截器实现类
      */
     public class Mylnterceptor 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动态代理,就可以实现这些方法在适当时的调用逻辑

  • 在JDK动态代理中使用拦截器以及test用例

     package com.yl.interceptor;
    
     import com.yl.jdk.HelloWorld;
     import com.yl.jdk.HelloWorldImpl;
    
     import java.lang.reflect.InvocationHandler;
     import java.lang.reflect.Method;
     import java.lang.reflect.Proxy;
    
     /**
      * 在JDK动态代理中使用拦截器
      */
     public class InterceptorJdkProxy implements InvocationHandler {
     
         private Object target = null;   //真实对象
         private String interceptorClass = null;     //拦截器全限定名
     
         public InterceptorJdkProxy(Object target, String interceptorClass) {
             this.target = target;
             this.interceptorClass = interceptorClass;
         }
    
         /**
          * 绑定委托对象并返回一个【代理占位】
          * @param target    真实对象
          * @param interceptorClass
          * @return  代理对象【占位】
          */
         public static Object bind(Object target,String interceptorClass) {
             //取得代理对象
             return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                     target.getClass().getInterfaces(),
                     new InterceptorJdkProxy(target,interceptorClass));
         }
    
         /**
          * 通过代理对象调用方法,首先进入这个方法
          * @param proxy     代理对象
          * @param method    方法,被调用方法
          * @param args      方法的参数
          * @return
          * @throws Throwable
          */
         @Override
         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)) {
                 //返回true,反射原有对象的方法
                 result = method.invoke(target,args);
             }else {
                 //返回false,执行around方法
                 interceptor.around(proxy,target,method,args);
             }
    
             //调用后置方法
             interceptor.after(proxy,target,method,args);
             return result;
         }
    
         public static void main(String[] args) {
             //注册拦截器
             HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),
                     "com.yl.interceptor.Mylnterceptor");
             //不注册拦截器
             HelloWorld proxy2 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),null);
    
             /**
              * 结果
              *  反射方法前逻辑---判断用户是否处于登录状态---用户未登录,操作拦截
              *  取代了被代理对象的方法---页面转发为指定界面,比如登录界面
              *  反射方法后逻辑---记录本次异常操作
              */
             proxy.sayHelloWorld();
     
             /**
              * 结果
              *  Hello World !
              */
             proxy2.sayHelloWorld();
         }
     }
    

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

     	第 1 步,在 bind 方法中用 JDK 动态代理绑定了一个对象,然后返回代理对象。 
     	第 2 步, 如果没有设置拦截器, 则直接反射真实对象的方法,然后结束,否则进行第 3 步。 
     	第 3 步,通过反射生成拦截器,并准备使用它。
     	第 4 步,调用拦截器的 before 方法,如果返回为 true,反射原来的方法;否则运行拦 截器的 around 方法。 
     	第 5 步,调用拦截器的 after 方法。 
     	第 6 步,返回结果。
    

在这里插入图片描述

  • HelloWorld接口

     /**
      *  JDK动态代理:必须借助一个接口才能产生代理对象,因此必须先定义接口。
     */
     public interface HelloWorld {
         public void sayHelloWorld();
     }
    
  • 提供HelloWorld的实现类来实现接口

     /**
      * 提供HelloWorld的实现类来实现接口
      */
     public class HelloWorldImpl implements HelloWorld{
         @Override
         public void sayHelloWorld() {
             System.out.println("Hello World !");
         }
     }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值