java 动态代理
有关Java的动态代理用法,写了一个demo,代码如下:
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() {@Overridepublic void addUser(String username) {System.out.println("addUser:" + username);}@Overridepublic void deleteUser(int id) {System.out.println("删除用户ID:" + id);}@Overridepublic 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;}@Overridepublic 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. 动态代理可以用于拦截接口调用,修改其实现,或者可以加日志、监控性能、敏感接口权限校验等等。这有利用业务解耦。某些框架也使用到动态代理。缺点就是使用反射对性能有损耗。