介绍了动态代理的定义、优势、jvm动态代理实现方式、通过Consumer定制化前置和后置方法。
一、动态代理的定义
动态代理(Dynamic Proxy)是 Java 提供的一种在运行时动态生成代理对象的机制,相较于静态代理为每个目标类都定义一个代理类,动态代理只需要一个实现InvocationHandler的类,通过Proxy.newProxyInstance方法即可自动创建各种目标类的代理类,其原理是反射,速度相较于CGLIB速度较慢。通过 java.lang.reflect.Proxy
类和 InvocationHandler
接口,我们可以实现对原始方法的拦截增强,常用于以下场景:
二、动态代理的三大优点
优势 |
说明 |
代码解耦 |
将通用逻辑(如日志)与业务代码分离 |
高复用性 |
一个代理处理器可服务于多个接口 |
运行时动态生成 |
无需为每个类手动编写代理,由 JVM 动态创建代理类 |
三、基础使用示例
3.1 定义接口与实现类
1 2 3 4 5 6 7 8 9
| interface UserService { void addUser(String name); }
class UserServiceImpl implements UserService { public void addUser(String name) { System.out.println("添加用户: " + name); } }
|
3.2 通用代理实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class BasicProxy implements InvocationHandler { private final Object target;
public BasicProxy(Object target) { this.target = target; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("【前置通知】"); Object result = method.invoke(target, args); System.out.println("【后置通知】"); return result; } public static Object createProxy(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new BasicProxy(target) ); } }
|
四、使用 Consumer 实现灵活拦截
4.1 函数式接口 Consumer
java.util.function.Consumer<T>
是 Java 8 引入的函数式接口,其核心方法是:
特点:
4.2 增强型代理实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class EnhancedProxy implements InvocationHandler { private final Object target; private final Consumer<Method> before; private final Consumer<Method> after;
public EnhancedProxy(Object target, Consumer<Method> before, Consumer<Method> after) { this.target = target; this.before = before; this.after = after; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before.accept(method); Object result = method.invoke(target, args); after.accept(method); return result; } }
|
五、自定义前后置方法实战
5.1 为不同接口定制逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| UserService userService = (UserService) Proxy.newProxyInstance( UserServiceImpl.class.getClassLoader(), new Class[]{UserService.class}, new EnhancedProxy( new UserServiceImpl(), method -> System.out.println(">>> 用户操作开始: " + method.getName()), method -> System.out.println("<<< 用户操作结束: " + method.getName()) ) );
EntertainmentService es = (EntertainmentService) Proxy.newProxyInstance( MovieService.class.getClassLoader(), new Class[]{EntertainmentService.class}, new EnhancedProxy( new MovieService(), method -> System.out.println("★ 娱乐活动准备: " + method.getName()), method -> System.out.println("☆ 活动结束耗时统计...") ) );
|
5.2 执行效果
1 2 3 4 5 6 7
| >>> 用户操作开始: addUser 添加用户: Alice <<< 用户操作结束: addUser
★ 娱乐活动准备: playMovie 播放电影: 星际穿越 ☆ 活动结束耗时统计...
|
六、架构优化总结
方案 |
优点 |
适用场景 |
基础代理 |
实现简单,快速上手 |
所有方法需要相同增强逻辑 |
增强型代理 |
支持不同接口的差异化处理 |
需要灵活定制拦截逻辑的场景 |
最佳实践建议:
- 使用 Lambda 表达式简化
Consumer
实现
- 通过工厂模式封装代理创建过程
- 结合注解实现更精细化的方法级控制
代码附录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.function.Consumer;
interface UserService { void addUser(String username); void deleteUser(String username); }
class UserServiceImpl implements UserService { @Override public void addUser(String username) { System.out.println("Adding user: " + username); }
@Override public void deleteUser(String username) { System.out.println("Deleting user: " + username); } }
interface Girl { void watchTV(); }
class Daughter implements Girl { @Override public void watchTV() { System.out.println("watching TV"); } }
class ServiceProxy implements InvocationHandler { private final Object target; private final Consumer<Method> before; private final Consumer<Method> after;
public ServiceProxy(Object target, Consumer<Method> before, Consumer<Method> after) { this.target = target; this.before = before; this.after = after; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before.accept(method); Object result = method.invoke(target, args); after.accept(method); return result; }
public Object getProxyInstance() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this ); } }
public class p1 { public static void main(String[] args) { UserService userService = new UserServiceImpl(); ServiceProxy userProxy = new ServiceProxy( userService, method -> System.out.println("[用户服务] 准备执行: " + method.getName()), method -> System.out.println("[用户服务] 完成执行: " + method.getName()) ); UserService proxyUserService = (UserService) userProxy.getProxyInstance(); proxyUserService.addUser("Alice"); proxyUserService.deleteUser("Bob");
Daughter daughter = new Daughter(); ServiceProxy girlProxy = new ServiceProxy( daughter, method -> System.out.println("[女孩行为] 方法开始: " + method.getName()), method -> System.out.println("[女孩行为] 方法结束: " + method.getName()) ); Girl mother = (Girl) girlProxy.getProxyInstance(); mother.watchTV(); } }
|