分享

java设计模式基础--拦截器

 小世界的野孩子 2021-07-05

由于动态代理一般比较难理解,一般都会设计一个拦截器接口供开发者使用,这样开发者就只用知道拦截器接口的方法,含义和作用即可,无须知道动态代理是怎么实现的。

以下代码用JDK动态代理来实现一个拦截器的逻辑。

一,定义拦截器接口:

package intercept;

import java.lang.reflect.Method;

public interface Interceptor {
    
    public boolean before(Object proxy, Object target, Method method, Object[] args);

    public void around(Object proxy, Object target, Method method, Object[] args);

    public void after(Object proxy, Object target, Method method, Object[] args);
}

before方法在真实对象调用前,当返回true时,则反射真实对象,当返回false时,则调用around方法。

二,定义拦截器接口实现类:

package intercept;

import java.lang.reflect.Method;

public class MyInterceptor implements Interceptor {
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.err.println("反射方法前逻辑");
                return true;
        // return false;// 不反射被代理对象原有方法
    }

    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.err.println("反射方法后逻辑。");
    }

    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        System.err.println("取代了被代理对象的方法");
    }
}
        

三,在JDK动态代理(JDK动态代理介绍)中使用拦截器:

package intercept;

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

public class InterceptorJdkProxy implements InvocationHandler {

    private Object target; //真实对象
    private String interceptorClass = null;//拦截器全限定名
    
    public InterceptorJdkProxy(Object target, String interceptorClass) {
        this.target = target;
        this.interceptorClass = interceptorClass;
    }

    /**
     * 绑定委托对象并返回一个【代理占位】
     *
     * @param target 真实对象
     * @return 代理对象【占位】
     */
    public static Object bind(Object target, String interceptorClass) {
        //取得代理对象    
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), 
                new InterceptorJdkProxy(target, interceptorClass));
    }

    @Override
    /**
     * 通过代理对象调用方法,首先进入这个方法.
     *
     * @param proxy --代理对象
     * @param method --方法,被调用方法
     * @param args -- 方法的参数
     */
    
    //反射出类对象
    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;
    }
}

五,定义需要被动态代理的类

因为是JDK动态代理,所以先定义接口:

package intercept;

public interface HelloWorld {
    public void sayHelloWorld();
}

实现接口:

package intercept;

public class HelloWorldImpl implements HelloWorld {

    @Override
    public void sayHelloWorld() {
        // TODO Auto-generated method stub
        System.out.println("Hello World");
    }

}

六,编写测试代码:

package intercept;


public class TestInterceptor {
    public static void main(String[] args) {
        HelloWorldImpl obj = new HelloWorldImpl();//被代理对象
        String myInterceptor = "com.lean.ssm.chapter2.intercept.MyInterceptor";// 自己定义的拦截器全限定名
        HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(obj, myInterceptor);
        proxy.sayHelloWorld();
    }
    
}

拦截器可以进一步简化动态代理使用方法,使程序变得简单。

 

七,参考资料

《java EE 互联网框架整合开发》 杨开振  著

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多