当前位置: 首页 > wzjs >正文

公司网站制作企业百度号注册官网

公司网站制作企业,百度号注册官网,辽宁建设网站,电信宽带做网站服务器吗动态代理 文章目录 动态代理先来看一个示例定义接口实现接口创建动态代理类测试动态代理输出结果关键点解析 CGLIB 动态代理定义目标类(无需实现接口)创建 CGLIB 动态代理测试代码 JDK 动态代理 vs CGLIB 动态代理为什么需要使用代理对象?动态…

动态代理

文章目录

  • 动态代理
    • 先来看一个示例
      • 定义接口
      • 实现接口
      • 创建动态代理类
      • 测试动态代理
      • 输出结果
      • 关键点解析
    • CGLIB 动态代理
      • 定义目标类(无需实现接口)
      • 创建 CGLIB 动态代理
      • 测试代码
    • JDK 动态代理 vs CGLIB 动态代理
    • 为什么需要使用代理对象?
    • 动态代理适合的场景
    • 动态代理的优势
    • 什么时候不适合使用动态代理?
    • Spring 中动态代理的主要应用场景包括:
      • AOP(面向切面编程)
      • 事务管理
    • Spring 中动态代理的主要应用场景包括:
      • AOP(面向切面编程)
      • 事务管理

先来看一个示例

定义接口

// 定义一个业务接口
public interface UserService {void addUser(String name);void deleteUser(String name);
}

实现接口

// 实现接口的业务逻辑
public class UserServiceImpl implements UserService {@Overridepublic void addUser(String name) {System.out.println("添加用户: " + name);}@Overridepublic void deleteUser(String name) {System.out.println("删除用户: " + name);}
}

创建动态代理类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 动态代理处理器
public class UserServiceProxyHandler implements InvocationHandler {private Object target; // 被代理的目标对象public UserServiceProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 方法调用前增强逻辑System.out.println("代理前: 准备执行方法 " + method.getName());// 执行目标方法Object result = method.invoke(target, args);// 方法调用后增强逻辑System.out.println("代理后: 方法 " + method.getName() + " 执行完成");return result;}// 获取代理对象public Object getProxy() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),         // 类加载器target.getClass().getInterfaces(),          // 目标对象实现的接口this                                       // 当前InvocationHandler实例);}
}

测试动态代理

public class DynamicProxyTest {public static void main(String[] args) {// 创建目标对象UserService userService = new UserServiceImpl();// 创建代理处理器并获取代理对象UserService proxyService = (UserService) new UserServiceProxyHandler(userService).getProxy();// 调用代理对象的方法proxyService.addUser("Alice");proxyService.deleteUser("Bob");}
}

输出结果

代理前: 准备执行方法 addUser
添加用户: Alice
代理后: 方法 addUser 执行完成
代理前: 准备执行方法 deleteUser
删除用户: Bob
代理后: 方法 deleteUser 执行完成

关键点解析

1.InvocationHandler 接口

  • proxy: 代理对象本身(通常不直接使用)
  • method: 被调用的目标方法
  • args: 方法参数

2.Proxy.newProxyInstance 方法

  • ClassLoader: 目标对象的类加载器
  • Class<?>[]: 目标对象实现的接口列表
  • InvocationHandler: 处理代理逻辑的处理器

3.适用场景

  • JDK 动态代理要求目标对象必须实现接口。如果目标对象没有实现接口,可以使用 CGLIB 动态代理。

4.扩展性

  • 可以在 invoke 方法中加入更多功能,如日志记录、性能监控、事务管理等。

CGLIB 动态代理

CGLIB 动态代理不要求目标对象实现接口,代理通过字节码生成子类的方式实现。

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

定义目标类(无需实现接口)

public class UserService {public void addUser(String name) {System.out.println("添加用户: " + name);}public void deleteUser(String name) {System.out.println("删除用户: " + name);}
}

创建 CGLIB 动态代理

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class CglibProxyHandler implements MethodInterceptor {private Object target; // 被代理的目标对象public CglibProxyHandler(Object target) {this.target = target;}public Object getProxy() {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass()); // 设置父类为目标类enhancer.setCallback(this);               // 设置回调return enhancer.create();                 // 创建代理对象}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("CGLIB代理前: 准备执行方法 " + method.getName());Object result = method.invoke(target, args); // 执行目标方法System.out.println("CGLIB代理后: 方法 " + method.getName() + " 执行完成");return result;}
}

测试代码

public class CglibProxyTest {public static void main(String[] args) {UserService userService = new UserService();UserService proxyService = (UserService) new CglibProxyHandler(userService).getProxy();proxyService.addUser("Alice");proxyService.deleteUser("Bob");}
}

JDK 动态代理 vs CGLIB 动态代理

特性JDKL动态代理CGLB动态代理
实现方式基于接口基于继承(生成子类)
目标对象要求必须实现接口不需要实现接口
性能接口调用效率较高子类生成效率较低,但运行时性能接近
适用场景目标对象有接口目标对象无接口或需要代理类本身的方法
局限性无法代理类本身的非接口方法无法代理 final 类或 final 方法

为什么需要使用代理对象?

即使你已经通过 new 创建了具体的对象,直接使用它也能完成业务逻辑,但这种方式存在以下局限性:

1. 代码侵入性强

如果你希望在方法调用前后添加一些通用逻辑(如日志记录、性能监控、事务管理等),直接修改原始类的代码会破坏单一职责原则,并且会导致代码冗余。

2.功能扩展困难

假设你需要为某些方法添加权限校验或缓存支持,直接修改原始类会让代码变得复杂且容易出错。而代理可以在不修改原始类的情况下,动态地添加这些功能。

3. 解耦与复用

通过代理模式,可以将核心业务逻辑与非核心逻辑(如日志、事务)分离,提升代码的可读性和复用性。

动态代理适合的场景

动态代理的主要目的是在运行时动态地为目标对象添加额外的行为,而不改变其原有代码。以下是动态代理的典型应用场景:

1. 日志记录

在方法调用前后记录日志,便于调试和审计。

System.out.println("代理前: 准备执行方法 " + method.getName());
Object result = method.invoke(target, args);
System.out.println("代理后: 方法 " + method.getName() + " 执行完成");

2.性能监控

统计方法的执行时间,用于性能优化。

long startTime = System.currentTimeMillis();
Object result = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println("方法执行耗时: " + (endTime - startTime) + "ms");

3. 事务管理

在方法调用前后开启和提交事务,确保数据一致性。

transactionManager.beginTransaction();
try {Object result = method.invoke(target, args);transactionManager.commit();return result;
} catch (Exception e) {transactionManager.rollback();throw e;
}

4. 权限校验

在方法调用前检查用户是否有权限执行该操作。

if (!securityManager.hasPermission(user, method)) {throw new SecurityException("无权访问");
}
return method.invoke(target, args);

5. 缓存支持

在方法调用前检查缓存中是否存在结果,避免重复计算。

String cacheKey = generateCacheKey(method, args);
if (cache.contains(cacheKey)) {return cache.get(cacheKey);
}
Object result = method.invoke(target, args);
cache.put(cacheKey, result);
return result;

6. 远程调用(RPC)

在分布式系统中,动态代理可以隐藏远程调用的细节,让开发者像调用本地方法一样调用远程服务。

// 动态代理实现 RPC 调用
Object result = rpcClient.invokeRemoteService(target, method, args);

动态代理的优势

  1. 透明性:动态代理对调用者是透明的,调用者无需关心代理的存在,只需像操作普通对象一样调用方法。
  2. 灵活性:代理逻辑可以在运行时动态生成,适用于多种场景(如日志、事务、权限等),而无需修改原始类。
  3. 解耦:将核心业务逻辑与非核心逻辑分离,符合单一职责原则和开闭原则。

什么时候不适合使用动态代理?

尽管动态代理非常强大,但它也有一些局限性,以下场景可能不适合使用动态代理:

1. 性能敏感场景

动态代理会引入一定的性能开销(尤其是 CGLIB),对于高频调用的场景可能需要权衡。

2. 简单任务

如果只是简单的功能调用,没有额外的需求(如日志、事务等),直接使用原始对象即可。

3. 静态需求

如果增强逻辑是固定的,且不需要动态生成,可以通过继承或装饰器模式实现。

Spring 中动态代理的主要应用场景包括:

AOP(面向切面编程)

  • 用于增强方法调用(如日志记录、性能监控、权限校验等)。
  • 示例:通过 @Aspect 注解定义切面逻辑。

事务管理

  • 用于声明式事务控制。
  • 示例:通过 @Transactional 注解实现事务管理。

定的性能开销(尤其是 CGLIB),对于高频调用的场景可能需要权衡。

2. 简单任务

如果只是简单的功能调用,没有额外的需求(如日志、事务等),直接使用原始对象即可。

3. 静态需求

如果增强逻辑是固定的,且不需要动态生成,可以通过继承或装饰器模式实现。

Spring 中动态代理的主要应用场景包括:

AOP(面向切面编程)

  • 用于增强方法调用(如日志记录、性能监控、权限校验等)。
  • 示例:通过 @Aspect 注解定义切面逻辑。

事务管理

  • 用于声明式事务控制。
  • 示例:通过 @Transactional 注解实现事务管理。
http://www.dtcms.com/wzjs/816028.html

相关文章:

  • wordpress 页面分栏河南seo推广平台
  • 公司后台的网站代理维护更新thinkphp 网站根目录地址
  • 汕头做网站费用做一个网上商城网站建设费用多少钱
  • dede 手机站 怎么获取跳转网站比较好的wordpress主题
  • 浙江省建设监理协会官方网站wordpress 5开发接口
  • 教师做爰网站建设网站创业
  • 培训心得体会范文临漳seo整站排名
  • 北京网站建设公司价格网站建设技术外包
  • 泰安手机网站建设公司虚拟机wordpress安装
  • 太原做网站需要多少钱建营销型网站
  • 网站备案授权网站优化就是seo
  • 德州极速网站建设小程序摄影网站设计说明书
  • 上海短视频推广公司怎么seo快速排名
  • 南宁做网站方案地方门户源码
  • 做招聘网站毕业设计网站建设存在哪些问题
  • 教育网站建站需求广东工程建设监理协会网站
  • qq空间怎么跟网站做链接吗c2c的网站
  • 医药招商网站建设网站建设公司 倒闭
  • 网站建设价类型公司网站一年多少钱
  • 杭州网站制作排名买东西哪个平台质量好
  • 视频网站用什么做做网站哪家公司便宜
  • 白山网站seo网站虚拟空间更新缓存
  • 加快网站平台建设有哪些做头像的网站
  • 广州市增城区建设局网站怎么做简历的网站
  • 手机网站模板更改吗长春专业网站建设推广
  • 什么是营销网络杭州江干区抖音seo品牌
  • 公司网站建设吧个好网站建设基本流程详细说明
  • 免费装修效果图网站郴州市网站建设公司
  • 网站个人中心wordpress域名备案通过后怎么做网站
  • 保定网站建陕西省建设厅执业资格注册中心网站报名系统