示例:
public class InstanceProxyUtils { //被代理的对象 public static class T { public void f() { System.out.println("测试"); } } public static class TMethodInvokeInterceptor implements MethodInterceptor { /** * 1. 代理对象的类是被代理类的子类 * <p> * 2. 代理对象重写了父类的所有方法 * 重写的结果时:调用代理对象的任何方法都会触发MethodInterceptor.intercept * <p> * 3. 当调用代理对象的方法时会将 代理对象自身/真实方法/调用参数/代理方法(调用时直接触发的方法,代理对象对父类方法的重写) 封装起来作为MethodInterceptor.intercept方法的入参 * <p> * 4. method.invoke(真实对象,params) 等价于 methodProxy.invokeSuper(代理对象,params) * <p> * 5. 注意:第一个参数(代理对象)慎用 * 5.1 切勿在MethodInterceptor.intercept方法中调用第一个参数proxy的任何方法,会引发无限递归最终OOM * proxy.toString->MethodInterceptor.intercept->proxy.toString->MethodInterceptor.intercept->...... * * @param proxy 代理对象 * @param method 被代理的类中的真实方法 * @param objects 调用时传入的参数 * @param methodProxy 代理对象中的代理方法 * @return 方法返回值 */ @Override public Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //这样也是允许的,等价于 method.invoke(new T(), objects); methodProxy.invoke(new T(), objects); //这样调用是允许的 methodProxy.invokeSuper(proxy, objects); //这样调用是不允许的,将会报强转异常,方法中会尝试将第一个参数强转为代理对象 //methodProxy.invokeSuper(new T(), objects); //这样会导致无限递归 method.invoke(proxy, objects)->MethodInterceptor.intercept->method.invoke(proxy, objects)->MethodInterceptor.intercept->.... //method.invoke(proxy, objects); //这样将会导致无限递归,原因和method.invoke(proxy, objects);相同 //methodProxy.invoke(proxy, objects); return null; } } public static void main(String[] args) { //代理对象的构建器 Enhancer enhancer = new Enhancer(); //设置代理对象的父类 enhancer.setSuperclass(T.class); //设置代理对象方法回调 enhancer.setCallback(new TMethodInvokeInterceptor()); //构建代理对象 T o = (T) enhancer.create(); o.f(); } }
几点疑问的解答:
1. 代理对象是否必须指向一个被代理对象?
否!根据实际需求,可以自定义拦截后的相关逻辑。