有关Java的动态代理用法,写了一个demo,代码如下:
java
package com.example.javalib;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
public class MyClass {
public static void main(String[] args) {
new MyClass().testProxy();
}
interface IUserService {
void addUser(String username);
void deleteUser(int id);
String getUser(int id);
}
private IUserService mUserService = new IUserService() {
@Override
public void addUser(String username) {
System.out.println("addUser:" + username);
}
@Override
public void deleteUser(int id) {
System.out.println("删除用户ID:" + id);
}
@Override
public String getUser(int id) {
System.out.println("获取用户,ID:" + id);
return "代号: " + id;
}
};
private void testProxy() {
System.out.println("原来调用流程:");
mUserService.addUser("小龙女");
mUserService.getUser(9527);
System.out.println("------------------------");
// 下面动态代理,原有功能不变,加点日志
class LoggingHandler implements InvocationHandler {
private IUserService target;
public LoggingHandler(IUserService target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("begin to invoke method: " + method.getName());
long start = System.currentTimeMillis();
// 为了原有功能保持不变,所以这里调用原始方法(是否调用原始方法根据业务需要, 甚至可以修改结果,也可以啥都不处理)
Object result = method.invoke(target, args);
long duration = System.currentTimeMillis() - start;
System.out.println("finish invoke method " + method.getName() + ", cost time: " + duration + "ms");
return result;
}
}
IUserService proxy = (IUserService) Proxy.newProxyInstance(IUserService.class.getClassLoader()
, new Class[]{IUserService.class}, new LoggingHandler(mUserService));
// 模拟的一些实际业务场景,这里我通过反射把mUserService替换了。
try {
Field field = MyClass.class.getDeclaredField("mUserService");
field.setAccessible(true);
field.set(MyClass.this, proxy);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("使用动态代理后调用流程:");
mUserService.addUser("小龙女");
mUserService.getUser(9527);
}
}
打印:

ok. 动态代理可以用于拦截接口调用,修改其实现,或者可以加日志、监控性能、敏感接口权限校验等等。这有利用业务解耦。某些框架也使用到动态代理。缺点就是使用反射对性能有损耗。