拦截器

Interceptor接口方法:

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);
}
  • 这里定义了3个方法,before、around、after,分别给予这些方法如下逻辑
  • 3个方法的参数:proxy代理对象,target真实对象,method方法、args参数
  • before方法返回boolean值,他在真实对象前调用。当返回true是,则反射真实对象的方法,当返回为false时,则调用around方法。
  • 在before方法返回为false,调用around方法。
  • 在反射真实对象或者around方法之后执行after方法。

MyInterceptor

public class MyInterceptor implements Interceptor {
	@Override
	public boolean before(Object proxy, Object target, Method method, Object[] args) {
		System.err.println("反射方法前逻辑");
		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动态代理中使用拦截器

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;
    }
}
  1. 在bind方法中使用JDK动态大力绑定一个对象,如何返回代理对象。
  2. 如果没有设置拦截器,则直接反射真实对象方法,如何结束,否则进行第3步。
  3. 通过反射生成拦截器,并准备使用它。
  4. 调用拦截器的before方法,如果返回为true,反射原来的方法;否则运行拦截器的around方法。
  5. 调用拦截器的after方法。
  6. 返回结果。
  • 开发者只要知道拦截器的作用就可以编写拦截器,编写完后可以设置拦截器,这样就完成了任务,所以对于开发者而言相对简单。
  • 设计者可能是精通Java的人员,他来完成动态代理的逻辑。
  • 设计者只会把拦截器接口暴露给开发者使用,让动态代理的逻辑在开发者的视野中“消失”。

Test类:

public class TestInterceptor {
	public static void main(String[] args) {
		testInterceptor();
		testChain();
	}
	
	
	public static void testInterceptor() {
		HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(), 
				"com.lean.ssm.chapter2.intercept.MyInterceptor");
		proxy.sayHelloWorld();
	}
	
	public static void testChain() {
		HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(
                new HelloWorldImpl(), "com.lean.ssm.chapter2.intercept.Interceptor1");
        HelloWorld proxy2 = (HelloWorld) InterceptorJdkProxy.bind(
                proxy1, "com.lean.ssm.chapter2.intercept.Interceptor2");
        HelloWorld proxy3 = (HelloWorld) InterceptorJdkProxy.bind(
                proxy2, "com.lean.ssm.chapter2.intercept.Interceptor3");
        proxy3.sayHelloWorld();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值