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

宝鸡做网站培训教育机构

宝鸡做网站,培训教育机构,泸州百拓网站建设,舟山建设信息港网站在Java开发中,动态代理是一种强大的机制,它允许我们在运行时创建代理对象,从而在不修改原有代码的情况下,对目标对象的方法进行增强。这种技术在AOP(面向切面编程)、RPC(远程过程调用&#xff0…

在Java开发中,动态代理是一种强大的机制,它允许我们在运行时创建代理对象,从而在不修改原有代码的情况下,对目标对象的方法进行增强。这种技术在AOP(面向切面编程)、RPC(远程过程调用)、ORM(对象关系映射)等领域有着广泛的应用。Java中实现动态代理主要有两种方式:JDK动态代理和CGLIB动态代理。

一、JDK动态代理

1. 原理

JDK动态代理是Java语言自带的代理实现方式,它基于Java的反射机制。当使用JDK动态代理时,代理类会实现目标对象所实现的接口,并在运行时动态生成。其核心在于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类负责创建代理对象,而InvocationHandler接口则定义了代理对象的方法调用逻辑。当代理对象的方法被调用时,实际会转发到InvocationHandlerinvoke方法,我们可以在invoke方法中对目标方法进行增强。

2. 特点

  • 基于接口: JDK动态代理只能代理实现了接口的类。如果目标对象没有实现任何接口,则无法使用JDK动态代理。
  • 运行时生成: 代理类在运行时动态生成,并加载到JVM中。
  • 性能: 在Java 8及以前的版本中,JDK动态代理的性能通常低于CGLIB。但在Java 9及以后的版本中,由于JVM对动态代理的优化,其性能已有所提升,甚至在某些场景下可以超越CGLIB。
  • 安全性: 由于是Java原生支持,相对更安全。

3. 适用场景

JDK动态代理适用于目标对象实现了接口的场景。例如,Spring AOP在默认情况下会优先使用JDK动态代理来为实现了接口的Bean创建代理。

4. JDK动态代理示例

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 定义一个接口
interface UserService {void sayHello(String name);
}// 实现接口的类
class UserServiceImpl implements UserService {@Overridepublic void sayHello(String name) {System.out.println("Hello, " + name + " from UserServiceImpl");}
}// 代理处理器
class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method: " + method.getName());Object result = method.invoke(target, args);System.out.println("After method: " + method.getName());return result;}
}public class JdkProxyDemo {public static void main(String[] args) {UserService userService = new UserServiceImpl();UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new MyInvocationHandler(userService));proxy.sayHello("World");}
}

二、CGLIB动态代理

1. 原理

CGLIB(Code Generation Library)是一个强大的、高性能的字节码生成库。它可以在运行时扩展Java类和实现Java接口。CGLIB动态代理的原理是通过继承目标类来创建代理类。它使用ASM(一个Java字节码操作框架)来修改字节码,生成目标类的子类,并在子类中重写父类的方法,从而实现方法的增强。当代理对象的方法被调用时,会通过CGLIB生成的代理类来调用,并执行我们定义的增强逻辑。

2. 特点

  • 基于类: CGLIB动态代理可以代理没有实现接口的类。它通过继承目标类来实现代理,因此目标类不能是final类,因为final类无法被继承。
  • 运行时生成: 代理类在运行时动态生成,并加载到JVM中。
  • 性能: 在Java 8及以前的版本中,CGLIB通常比JDK动态代理具有更好的性能,因为它直接操作字节码,避免了反射的开销。但在Java 9及以后的版本中,JDK动态代理的性能已有所提升,两者的性能差距逐渐缩小。
  • 侵入性: 相对于JDK动态代理,CGLIB对目标类有一定的侵入性,因为它需要继承目标类。

3. 适用场景

CGLIB动态代理适用于目标对象没有实现接口的场景,或者需要代理final方法以外的任何方法。Spring AOP在目标Bean没有实现接口时,会使用CGLIB动态代理。

4. CGLIB动态代理示例

首先,确保你的项目中引入了CGLIB的依赖:

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;// 没有实现接口的普通类
class ProductService {public void getProduct(String id) {System.out.println("Getting product with ID: " + id);}
}// 代理拦截器
class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method: " + method.getName());Object result = proxy.invokeSuper(obj, args);System.out.println("After method: " + method.getName());return result;}
}public class CglibProxyDemo {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(ProductService.class);enhancer.setCallback(new MyMethodInterceptor());ProductService proxy = (ProductService) enhancer.create();proxy.getProduct("123");}
}

三、JDK与CGLIB对比

特性JDK动态代理CGLIB动态代理
代理方式基于接口基于类继承
限制只能代理实现了接口的类不能代理final类和final方法
性能Java 8及以前版本通常低于CGLIB,Java 9+有所提升Java 8及以前版本通常优于JDK,Java 9+性能差距缩小
侵入性无侵入性对目标类有侵入性(继承)
原生支持Java原生支持第三方库支持

四、动态代理选择建议

在实际项目中,选择JDK动态代理还是CGLIB动态代理,主要取决于以下几个因素:

  1. 目标对象是否实现接口:

    • 如果目标对象实现了接口,并且你希望通过接口进行代理,那么JDK动态代理是首选。它简单、直接,并且是Java原生支持的。
    • 如果目标对象没有实现接口,或者你希望代理的是一个普通的类,那么CGLIB动态代理是唯一的选择。
  2. 性能要求:

    • 在大多数业务场景下,JDK和CGLIB的性能差异可以忽略不计。如果对性能有极致要求,并且在Java 8及以前的版本中,可以考虑CGLIB。但在Java 9及以后的版本中,建议进行实际测试,因为JDK动态代理的性能已大幅提升。
  3. 框架选择:

    • 许多主流框架(如Spring)会根据情况自动选择合适的代理方式。例如,Spring AOP在默认情况下,如果目标对象实现了接口,则使用JDK动态代理;否则,使用CGLIB动态代理。你也可以通过配置来强制指定代理方式。
  4. final类和final方法:

    • 如果目标类是final的,或者需要代理的方法是final的,那么CGLIB动态代理将无法工作,因为CGLIB通过继承来实现代理,而final类和final方法不能被继承或重写。在这种情况下,你可能需要重新考虑设计,或者寻找其他代理方案。

五、结论

JDK动态代理和CGLIB动态代理各有优劣,它们在Java生态系统中扮演着重要的角色。JDK动态代理是Java语言的内置功能,适用于基于接口的代理;而CGLIB则是一个强大的第三方库,适用于基于类的代理。在选择时,应根据目标对象的特性、性能要求以及所使用的框架等因素进行综合考量。

http://www.dtcms.com/wzjs/85748.html

相关文章:

  • 如何制作网页网站广告资源网
  • 陕西有没有做网站普查公司百度指数的网址是什么
  • 张雪峰谈网络工程站优云seo优化
  • 宜丰做网站的3d建模培训学校哪家好
  • 网站后面的官网是如何做的seo服务 文库
  • 钓鱼网站怎么做游戏代理平台
  • 怎样做自己的 优惠卷网站企业关键词排名优化网址
  • 有了域名 网站建设如何添加百度指数
  • 国内十大网站建设品牌我想注册一个网站怎么注册
  • 17种新型商业模式跨境电商seo什么意思
  • 网站备案去哪找接入商北京网络seo推广公司
  • seo网站分析案例新东方留学机构官网
  • 便宜购物网站大全找客源免费用哪个软件好
  • 网站建设合同书样本东莞疫情最新消息今天新增病例
  • 旅行社手机网站建设个人网站seo
  • 建设一个网站需要哪些功能seo网站推广的主要目的不包括
  • 购买域名网站百度一下知道官网
  • 初中做语文综合题的网站怎样做百度推广
  • 网络舆情管控措施网站seo需要用到哪些工具
  • 网站建设+开源百度ai人工智能
  • 梅州网站建设网络营销与直播电商专业介绍
  • 旅行网站排名河南网站关键词优化代理
  • 亚马逊网站建设进度计划表品牌营销公司
  • b2b贸易网站建设百度推广搜索排名
  • 手机版网站建设费用清单网络广告推广方案
  • 合肥网站建设网站制作互联网营销课程体系
  • 男女裸体直接做的视频网站百度账号申请注册
  • 设计网站建设图片百度快速收录开通
  • 广告位seo推广的公司
  • 微信公众号网站建设费抖音怎么推广引流