Java动态代理与方法拦截实战解析
在Java编程中,动态代理是一种强大的技术,它允许我们在运行时创建接口的代理实例,并且可以拦截方法调用。本文将通过一个具体的实例,详细解析如何使用JDK的动态代理机制来实现方法拦截,以及如何编写通用的方法拦截器。
实现InvocationHandler
首先,我们需要实现InvocationHandler
接口,这个接口定义了invoke
方法,用于拦截所有代理对象的方法调用。下面是一个简单的实现示例:
public class MyInvocationHandler implements InvocationHandler {
private String theString;
public MyInvocationHandler(String theString) {
this.theString = theString;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method call : " + method.getName());
Object result = method.invoke(theString, args);
System.out.println("after method call : " + method.getName());
return result;
}
}
创建并代理String对象
为了演示基本的概念,我们选择了java.lang.CharSequence
接口和它的实现类String。下面是如何将原始的String对象链接到它的代理CharSequence接口:
public static void main(String[] args) {
MyInvocationHandler handler = new MyInvocationHandler("the example string");
CharSequence o = (CharSequence) Proxy.newProxyInstance(
MyInvocationHandler.class.getClassLoader(),
new Class[]{CharSequence.class}, handler);
System.out.println(o.length());
System.out.println(o.subSequence(4, 8));
}
输出
before method call : length
after method call : length
18
before method call : subSequence
after method call : subSequence
exam
通用方法拦截器
接下来,我们将重写上面的拦截器,使其能够适用于任何对象:
public class MyInterceptor<T> implements InvocationHandler {
private T t;
public MyInterceptor(T t) {
this.t = t;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before method call : " + method.getName());
Object result = method.invoke(t, args);
System.out.println("after method call : " + method.getName());
return result;
}
@SuppressWarnings("unchecked")
public static <T> T getProxy(T t, Class<? super T> interfaceType) {
MyInterceptor handler = new MyInterceptor(t);
return (T) Proxy.newProxyInstance(interfaceType.getClassLoader(),
new Class<?>[]{interfaceType}, handler);
}
}
public class MyInterceptorExample {
public static void main(String[] args) {
List<String> list = MyInterceptor.getProxy(new ArrayList<>(), List.class);
list.add("one");
list.add("two");
System.out.println(list);
list.remove("one");
}
}
输出
before method call : add
after method call : add
before method call : add
after method call : add
before method call : toString
after method call : toString
[one, two]
before method call : remove
after method call : remove
示例项目
本示例项目使用了以下依赖和技术:
- JDK 1.8
- Maven 3.0.4
通过这个示例,我们可以看到动态代理如何在Java中实现AOP风格的’around advice’,以及如何通过InvocationHandler
来拦截和处理方法调用。希望这个实战解析能够帮助你更好地理解和使用Java的动态代理技术。