如何让JDK动态代理仅代理接口中的单个指定方法?
解决方案
JDK动态代理的InvocationHandler#invoke方法默认会接收该接口所有方法的调用请求,只需在方法内部增加匹配规则,仅对doSomething方法执行代理增强逻辑,其余方法直接转发到原对象执行即可。
实现方式1:方法名字符串匹配(简单直观)
直接判断当前调用方法的名称是否为doSomething,匹配成功才执行增强逻辑:
class DynamicProxy implements InvocationHandler{ private Action work; public DynamicProxy(Action action){ this.work = action; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 仅对doSomething方法做增强处理 if ("doSomething".equals(method.getName())) { System.out.println(method.getName()+" start"); Object result = method.invoke(work,args); System.out.println(method.getName()+" end"); return result; } // 其他方法直接调用原对象的对应方法,不做增强 return method.invoke(work,args); } }
代理对象生成逻辑不需要修改,和原有逻辑保持一致即可。
实现方式2:Method对象匹配(更安全)
预先获取目标方法的实例做比对,避免字符串拼写错误导致匹配失效的问题:
class DynamicProxy implements InvocationHandler{ private Action work; // 预先定义需要代理的方法实例 private final Method targetMethod; public DynamicProxy(Action action) throws NoSuchMethodException { this.work = action; this.targetMethod = Action.class.getMethod("doSomething"); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 比对方法对象,匹配成功才执行增强 if (method.equals(targetMethod)) { System.out.println(method.getName()+" start"); Object result = method.invoke(work,args); System.out.println(method.getName()+" end"); return result; } return method.invoke(work,args); } }
两种实现效果一致:调用action.doSomething()时会输出前后增强日志,调用action.dontProxy()时不会执行任何代理逻辑,直接返回原方法执行结果。
内容的提问来源于stack exchange,提问作者Adolphus Holmes
相关产品推荐
相关产品推荐

