拦截器(由JDK动态代理实现的拦截器)

Posted 茶尚温.听风吟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拦截器(由JDK动态代理实现的拦截器)相关的知识,希望对你有一定的参考价值。

要实现拦截器,首先我们需要定义几个类和接口

package com.xiawei.reflect.interceptor;

public interface JavaBenDao {

public void look();
}

 

==================================================

package com.xiawei.reflect.interceptor;

public class JavaBenDaoImpl implements JavaBenDao {

@Override
public void look() {
System.out.println("这是真实对象的方法!");
}

}

==================================================

这里要自定义一个拦截器的接口,并且定义了三个抽象的方法

before(),around(),after()。这三个方法分别被用在执行反射

方法前;取代被代理的对象时;在执行反射方法后三个节点。

 

package com.xiawei.reflect.interceptor;

import java.lang.reflect.Method;

/**
* 自定义拦截器的接口
* @author Administrator
*
*/
public interface InterceptorDao {

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

 

====================================================

package com.xiawei.reflect.interceptor;

import java.lang.reflect.Method;
/**
* 拦截器实现类
* @author Administrator
*
*/
public class InterceptorDaoImpl implements InterceptorDao{

@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("在执行反射方法前执行的逻辑!");
return true;//默认值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("在执行反射方法后执行的逻辑!");

}

}

 

====================================================

这里创建一个JDK动态代理类,再在动态代理中使用拦截器

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 在动态代理中使用拦截器</p>
* 动态代理类
* @author Administrator
*
*/
public class JdkInterceptorClass implements InvocationHandler {

/**
* 真实对象
*/
private Object target;
/**
* 拦截器的全限定名
*/
private String interceptorClass;

public JdkInterceptorClass(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 JdkInterceptorClass(target,interceptorClass));
}

/**
* 通过代理对象调用方法,首先进入invoke()
* @param proxy 代理对象
* @param method 被调用的方法
* @param args 方法参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断,如果拦截器全限定名为空,也就是没有设置拦截器则反射原有方法(真实对象的方法)
if(interceptorClass == null){
return method.invoke(target, args);
}

//通过反射生成拦截器
Object result = null;//定义执行以下逻辑后的返回值
InterceptorDao interceptor =
(InterceptorDao) 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;
}

}

 

=========================================================

好了,代码完成后我们测试一下,写个测试类

package com.xiawei.reflect.interceptor;

public class Test {

public static void main(String[] args) {
//获得代理对象
JavaBenDao proxy = (JavaBenDao) JdkInterceptorClass.bind(new JavaBenDaoImpl(),
"com.xiawei.reflect.interceptor.InterceptorDaoImpl");
//调用真实对象的方法
proxy.look();

}

运行结果:

  在执行反射方法前执行的逻辑!
  这是真实对象的方法!
  在执行反射方法后执行的逻辑!

可以将上面的 before()方法的返回值改为false试一下.哈哈

以上是关于拦截器(由JDK动态代理实现的拦截器)的主要内容,如果未能解决你的问题,请参考以下文章

Spring框架中的JDK与CGLib动态代理

逆水行舟 —— jdk动态代理和Cglib字节码增强

CGLIB与JDK动态代理

CGLIB与JDK动态代理

Cglib和jdk动态代理的区别

CGlib和JDK动态代理