Java动态代理

Java动态代理

标签: Java动态代理代理
719人阅读 评论(0) 收藏 举报
分类:

提到Java动态代理,必须首先说一下Java静态代理,也就是通常所说的代理模式:

  1. package com.sean;  
  2.   
  3. public class User {  
  4.     public Integer id;  
  5.     public String name;  
  6.       
  7.     public Integer getId() {  
  8.         return id;  
  9.     }  
  10.       
  11.     public void setId(Integer id) {  
  12.         this.id = id;  
  13.     }  
  14.       
  15.     public String getName() {  
  16.         return name;  
  17.     }  
  18.       
  19.     public void setName(String name) {  
  20.         this.name = name;  
  21.     }  
  22. }  
  1. package com.sean;  
  2.   
  3. public interface UserDAO {  
  4.     public boolean add(User user);  
  5.       
  6.     public boolean delete(Integer id);  
  7.       
  8.     public boolean modify(User user);  
  9.       
  10.     public Object query(Integer id);  
  11. }  
  1. package com.sean;  
  2.   
  3. public class UserDAOImpl implements UserDAO {  
  4.     @Override  
  5.     public boolean add(User user) {  
  6.         System.out.println("Add a new user");  
  7.         return true;  
  8.     }  
  9.   
  10.     @Override  
  11.     public boolean delete(Integer id) {  
  12.         System.out.println("Delete a new user");  
  13.         return true;  
  14.     }  
  15.   
  16.     @Override  
  17.     public boolean modify(User user) {  
  18.         System.out.println("Modify a new user");  
  19.         return true;  
  20.     }  
  21.   
  22.     @Override  
  23.     public Object query(Integer id) {  
  24.         System.out.println("Query a new user");  
  25.         return new User();  
  26.     }  
  27. }  

UserDAOImpl类的代理类

  1. package com.sean;  
  2.   
  3. public class UserDAOProxy implements UserDAO {  
  4.     private UserDAO userDAO;  
  5.       
  6.     public UserDAOProxy(UserDAO userDAO){  
  7.         this.userDAO = userDAO;  
  8.     }  
  9.   
  10.     @Override  
  11.     public boolean add(User user) {  
  12.         this.beginTransaction();  
  13.         boolean result = userDAO.add(user);  
  14.         this.endTransaction();  
  15.         return result;  
  16.     }  
  17.   
  18.     @Override  
  19.     public boolean delete(Integer id) {  
  20.         this.beginTransaction();  
  21.         boolean result = userDAO.delete(id);  
  22.         this.endTransaction();  
  23.         return result;  
  24.     }  
  25.   
  26.     @Override  
  27.     public boolean modify(User user) {  
  28.         this.beginTransaction();  
  29.         boolean result = userDAO.modify(user);  
  30.         this.endTransaction();  
  31.         return result;  
  32.     }  
  33.   
  34.     @Override  
  35.     public Object query(Integer id) {  
  36.         this.beginTransaction();  
  37.         Object obj = userDAO.query(id);  
  38.         this.endTransaction();  
  39.         return obj;  
  40.     }  
  41.       
  42.     private void beginTransaction(){  
  43.         System.out.println("Begin transaction");  
  44.     }  
  45.       
  46.     private void endTransaction(){  
  47.         System.out.println("End transaction");  
  48.     }  
  49. }  

从上面的代码中我们可以发现静态代理一个很明显的问题就是重复代码太多,不利于维护

当然如果想要使用动态代理,目标类必须是一个接口实现类,由于UserDAOImpl是一个接口实现类,满足使用Java动态代理的条件,我们可以使用Java动态代理避免出现太多重复性代码的问题

对于非接口实现类,CGlib可以作为动态代理一个很好的补充

看到这里是不是想到了spring AOP的应用场景?没错,Spring AOP也是使用Java动态代理实现的(针对非接口实现类,Spring AOP使用CGlib实现)

  1. package com.sean;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5. import java.lang.reflect.Proxy;  
  6.   
  7. public class TransactionHandler implements InvocationHandler {  
  8.     private UserDAO userDAO;  
  9.       
  10.     @Override  
  11.     public Object invoke(Object proxy, Method method, Object[] args)  
  12.             throws Throwable {  
  13.         this.beginTransaction();  
  14.         Object obj =  method.invoke(userDAO, args);  
  15.         this.endTransaction();  
  16.         return obj;  
  17.     }  
  18.       
  19.     public UserDAO createProxy(UserDAO userDAO){  
  20.         this.userDAO = userDAO;  
  21.         return (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(),   
  22.                 userDAO.getClass().getInterfaces(), this);  
  23.     }  
  24.       
  25.     private void beginTransaction(){  
  26.         System.out.println("Begin transaction");  
  27.     }  
  28.       
  29.     private void endTransaction(){  
  30.         System.out.println("End transaction");  
  31.     }  
  32. }  
  1. package com.sean;  
  2.   
  3. public class Test {  
  4.     public static void main(String[] args) {  
  5.         UserDAO userDAO = new UserDAOImpl();  
  6.         TransactionHandler th = new TransactionHandler();  
  7.         UserDAO userDAOProxy = th.createProxy(userDAO);  
  8.         userDAOProxy.add(new User());  
  9.     }  
  10. }  

UserDAO的代理类及其实例是在运行期间由Proxy的newProxyInstance动态生成的,所以被称为动态代理

从代码中可以看到,动态代理不但快捷方便而且对原代码没有任何侵入性

内容概要:《中文大模型基准测评2025年上半年报告》由SuperCLUE团队发布,详细评估了2025年上半年中文大模型的发展状况。报告涵盖了大模型的关键进展、国内外大模型全景图及差距、专项测评基准介绍等。通过SuperCLUE基准,对45个国内外代表性大模型进行了六大任务(数学推理、科学推理、代码生成、智能体Agent、精确指令遵循、幻觉控制)的综合测评。结果显示,海外模型如o3、o4-mini(high)在推理任务上表现突出,而国内模型如Doubao-Seed-1.6-thinking-250715在智能体Agent和幻觉控制任务上表现出色。此外,报告还分析了模型性价比、效能区间分布,并对代表性模型如Doubao-Seed-1.6-thinking-250715、DeepSeek-R1-0528、GLM-4.5等进行了详细介绍。整体来看,国内大模型在特定任务上已接近国际顶尖水平,但在综合推理能力上仍有提升空间。 适用人群:对大模型技术感兴趣的科研人员、工程师、产品经理及投资者。 使用场景及目标:①了解2025年上半年中文大模型的发展现状与趋势;②评估国内外大模型在不同任务上的表现差异;③为技术选型和性能优化提供参考依据。 其他说明:报告提供了详细的测评方法、评分标准及结果分析,确保评估的科学性和公正性。此外,SuperCLUE团队还发布了多个专项测评基准,涵盖多模态、文本、推理等多个领域,为业界提供全面的测评服务。
### Java 动态代理的实现原理与用法 #### 1. Java 动态代理概述 Java 动态代理是一种在运行时动态生成代理对象的技术,它允许开发者无需提前定义具体的代理即可完成方法拦截和增强功能。这种机制广泛应用于 AOP(面向切面编程)、事务管理以及日志记录等领域[^2]。 #### 2. 动态代理的核心组件 动态代理主要依赖于 `java.lang.reflect.Proxy` 和 `InvocationHandler` 接口来实现。以下是其核心组成部分: - **Proxy **: 提供了用于创建动态代理实例的方法。 - **InvocationHandler 接口**: 定义了一个处理方法调用的回调接口,通过该接口可以自定义代理行为。 当客户端调用代理对象上的某个方法时,实际执行的是由 InvocationHandler 处理逻辑所指定的操作[^3]。 #### 3. JDK 原生动态代理实现 JDK 动态代理基于反射技术,在运行期间为一组接口动态生成代理及其实例。具体流程如下: - 创建一个实现了 `InvocationHandler` 接口的对象。 - 使用 `Proxy.newProxyInstance()` 方法传入目标加载器、目标实现的一组接口列表以及上述 handler 对象,从而获得代理实例。 下面是一个简单的示例代码展示如何利用 JDK 动态代理实现基本的日志打印功能: ```java import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 定义服务接口 interface GreetingService { void sayHello(String name); } // 实现服务接口的具体业务逻辑 class SimpleGreetingServiceImpl implements GreetingService { @Override public void sayHello(String name) { System.out.println("Hello, " + name); } } // 自定义 InvocationHandler 来拦截并扩展方法调用 class LoggingInvocationHandler implements InvocationHandler { private Object target; // 被代理的目标对象 public LoggingInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("[Before] Executing: " + method.getName()); // 执行原始方法 Object result = method.invoke(target, args); System.out.println("[After] Finished execution."); return result; } } public class JdkDynamicProxyDemo { public static void main(String[] args) { // 初始化真实的服务实现 GreetingService greetingService = new SimpleGreetingServiceImpl(); // 构建带有日志功能的代理对象 GreetingService proxyInstance = (GreetingService) Proxy.newProxyInstance( greetingService.getClass().getClassLoader(), greetingService.getClass().getInterfaces(), new LoggingInvocationHandler(greetingService)); // 测试代理效果 proxyInstance.sayHello("World"); } } ``` 此程序展示了如何通过动态代理增加额外的功能而不修改原有代码结构[^1]。 #### 4. CGLib 动态代理实现 除了 JDK 内置支持外,还可以借助第三方库如 CGLib 进行动态代理操作。CGLib 主要针对那些未继承任何接口或者希望直接操控实体场景下更为适用。它的内部工作机理涉及字节码层面操作,能够子化任意非 final 的普通,并重写其中的方法达到相同目的。 需要注意的是,由于两者设计初衷不同,在性能表现上可能会有所差异;通常情况下,如果仅需对接口做封装,则推荐优先考虑更轻量级也更加直观易懂的 JDK 方案。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值