JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(4):JDK动态代理+拦截器

一、拦截器的理解

  学习拦截器之前需要对动态代理和反射有一定的基础。

  官方说法:

          java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。 

      简单来说,就是拦截器可以提供一个在方法调用之前的方法,调用之后的方法,方便我们在方法执行的前后做拦截判或其他业务处理。

二、Jdk动态代理+拦截器

创建一个普通接口:HelloWorld.java

1 package com.xfwl.proxy.jdk;
2 
3 public interface HelloWorld {
4     public void  sayHelloWorld();
5 }

 创建一个上面皆接口的实现子类:HelloWorldImpl.java

1 package com.xfwl.proxy.jdk;
2 
3 public class HelloWorldImpl implements HelloWorld {
4 
5     public void sayHelloWorld() {
6         System.out.println("Hello World!");
7     }
8 }

 创建一个拦截器的接口:Interceptor.java

package com.xfwl.interceptor;

import java.lang.reflect.Method;

/**
 * 定义一个拦截器接口
 * @function  
 * @author 小风微凉
 * @time  2018-7-9 下午2:20:35
 */
public interface Interceptor {
    /**
     * 拦截器-真实方法调用之前before
     * @param proxy 代理对象
     * @param target 真实对象
     * @param method 真实方法
     * @param args 运行参数
     * @return 返回boolean  false则执行around(),true则不执行around()
     */
    public boolean before(Object proxy,Object target,Method method,Object[] args);
    /**
     * before()返回 false则执行around(),true则不执行around()
     * @param proxy 代理对象
     * @param target 真实对象
     * @param method 真实方法
     * @param args 运行参数
     */
    public void around(Object proxy,Object target,Method method,Object[] args);
    /**
     * before/around执行之后执行after()
     * @param proxy 代理对象
     * @param target 真实对象
     * @param method 真实方法
     * @param args 运行参数
     */
    public void after(Object proxy,Object target,Method method,Object[] args);
}

 创建上面拦截器接口的实现子类:MyInterceptor.java

 1 package com.xfwl.interceptor;
 2 
 3 import java.lang.reflect.Method;
 4 /**
 5  * 拦截器实现子类
 6  * @function 理解拦截器之前需要理解动态代理+反射机制 
 7  * @author 小风微凉
 8  * @time  2018-7-9 下午2:25:34
 9  */
10 public class MyInterceptor implements Interceptor {
11 
12     @Override
13     public boolean before(Object proxy, Object target, Method method,Object[] args) {
14         System.out.println("反射方法前逻辑!");        
15         return false;
16     }
17 
18     @Override
19     public void around(Object proxy, Object target, Method method, Object[] args) {
20         System.out.println("取代了被代理对象的方法!");    
21     }
22 
23     @Override
24     public void after(Object proxy, Object target, Method method, Object[] args) {
25         System.out.println("反射方法后逻辑!");
26     }
27 }

 创建一个动态代理类:InterceptorJdkProxy.java

 1 package com.xfwl.interceptor;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 /**
 7  * JDK动态代理实现类
 8  * @function  在代理类中嵌入拦截器,关键点还是动态代理
 9  * @author 小风微凉
10  * @time  2018-7-9 下午2:29:21
11  */
12 public class InterceptorJdkProxy implements InvocationHandler {
13     //真实对象
14     private Object target=null;
15     //拦截器全称
16     private String interceptorClass=null;
17     //动态代理类构造器
18     public InterceptorJdkProxy(){}
19     public InterceptorJdkProxy(Object target,String interceptorClass){
20         this.interceptorClass=interceptorClass;
21         this.target=target;
22     }
23     /**
24      *  给真实独享绑定代理对象
25      * @param target  真实对象
26      * @param interceptorClass  拦截器的全称
27      * @return 代理对象【占位】
28      */
29     public  Object bind(Object target,String interceptorClass){
30         return Proxy.newProxyInstance(
31                 target.getClass().getClassLoader(),//真实对象的类加载器
32                 target.getClass().getInterfaces(), //真实对象的实现接口
33                 new InterceptorJdkProxy(target, interceptorClass)//实现了InvocationHandler接口的实现类,一般为当前代理类对象
34         );            
35     }    
36     /**
37      * 通过代理对象调用方法,首先进入这个方法
38      * @param proxy 代理对象
39      * @param method 方法
40      * @param args 运行参数
41      * @return 
42      */
43     @Override
44     public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
45         //判断当前代理是否使用了拦截器
46         if(interceptorClass==null){
47             //没有拦截器,则直接执行真实对象的方法
48             return method.invoke(this.target, args);
49         }
50         Object result=null;
51         //通过反射拿到拦截器对象
52         Interceptor interceptor =(Interceptor)Class.forName(interceptorClass).newInstance(); 
53         //调用前置方法
54         if(interceptor.before(proxy, args, method, args)){
55             //反射真实对象原有的方法
56             result=method.invoke(target, args);
57         }else{
58             //返回false,执行around方法
59             interceptor.around(proxy, args, method, args);
60         }
61         //调用后置方法
62         interceptor.after(proxy, args, method, args);        
63         return result;
64     }
65 }

 创建一个测试类:TestInterceptor.java.

 1 package com.xfwl.interceptor;
 2 
 3 import com.xfwl.proxy.jdk.HelloWorld;
 4 import com.xfwl.proxy.jdk.HelloWorldImpl;
 5 
 6 /**
 7  * 拦截器测试
 8  * @function  测试一下拦截器是如何起作用的,
 9  * @author 小风微凉
10  * @time  2018-7-9 下午2:19:15
11  */
12 public class TestInterceptor {
13 
14     /**  
15      * @param args
16      */
17     public static void main(String[] args) {
18         //拿到代理对象,并绑定真实对象
19         HelloWorld proxy=(HelloWorld) new InterceptorJdkProxy().bind(
20                                                 new HelloWorldImpl(), 
21                                                 "com.xfwl.interceptor.MyInterceptor"
22                                                 );
23         //执行代理逻辑
24         proxy.sayHelloWorld();
25 
26     }
27 
28 }

 测试结果:

运行条件【1】:

1 @Override
2     public boolean before(Object proxy, Object target, Method method,Object[] args) {
3         System.out.println("反射方法前逻辑!");        
4         return false;
5     }

 运行结果:

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

 运行条件【2】:

1 @Override
2     public boolean before(Object proxy, Object target, Method method,Object[] args) {
3         System.out.println("反射方法前逻辑!");        
4         return true;
5     }

 运行结果:

反射方法前逻辑!
Hello World!
反射方法后逻辑!

 从上面可以看出,拦截器生效了!

猜你喜欢

转载自www.cnblogs.com/newwind/p/9283934.html