代理模式在java中主要有四种实现方式。1. 静态代理需手动编写代理类,通过持有目标类引用并添加额外逻辑,适合小规模项目但代码冗余;2. jdk动态代理基于接口,利用proxy和invocationhandler在运行时生成代理对象,灵活但仅限接口代理;3. cglib代理通过继承目标类并重写方法实现,可代理无接口类,适用范围广但无法处理final类或方法;4. spring aop根据目标类是否实现接口自动选择jdk或cglib代理,也可强制使用cglib,使开发者无需关注底层实现。

代理模式在Java中是一种常见的设计模式,主要用于控制对象的访问、增强功能或延迟加载。它通过一个代理类来间接操作目标对象,常用于AOP编程、远程调用(RMI)、权限控制等场景。

Java中实现代理的方式有多种,下面从常见且实用的角度出发,分别介绍几种主流的代理实现方式。

静态代理:手动编写代理类
静态代理是最基础也是最容易理解的一种代理方式。它的特点是需要为每一个目标类手动编写一个对应的代理类。
立即学习“Java免费学习笔记(深入)”;
实现步骤如下:
定义一个公共接口实现目标类编写代理类,持有目标类的引用,并在其方法前后添加额外逻辑
举个例子:
public interface Service { void doSomething();}public class RealService implements Service { public void doSomething() { System.out.println("Doing something..."); }}public class StaticProxy implements Service { private Service target; public StaticProxy(Service target) { this.target = target; } public void doSomething() { System.out.println("Before method call"); target.doSomething(); System.out.println("After method call"); }}
这种方式优点是结构清晰,缺点是代码冗余,每增加一个服务都需要一个新的代理类。
JDK动态代理:基于接口的运行时代理生成
JDK动态代理是Java自带的功能,利用java.lang.reflect.Proxy类和InvocationHandler接口实现在运行时动态创建代理对象。
关键点在于:
目标类必须实现至少一个接口通过Proxy.newProxyInstance()方法生成代理实例所有对代理对象的方法调用都会转发到invoke()方法中处理
示例代码:
Service proxy = (Service) Proxy.newProxyInstance( Service.class.getClassLoader(), new Class[]{Service.class}, new InvocationHandler() { private Object target = new RealService(); public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK Proxy: before"); Object result = method.invoke(target, args); System.out.println("JDK Proxy: after"); return result; } });proxy.doSomething();
这种方式的优点是灵活性高,无需手动编写代理类。但局限也很明显:只能对接口进行代理,不能代理没有实现接口的类。
CGLIB代理:基于继承的字节码增强
CGLIB是一个强大的第三方库,它通过继承目标类并重写其方法的方式来生成代理类,因此可以代理没有实现接口的类。
使用CGLIB的关键组件是Enhancer类和MethodInterceptor接口。
基本流程如下:
创建Enhancer实例设置父类(即目标类)设置回调函数(即拦截器)调用create()方法生成代理对象
简单示例:
Enhancer enhancer = new Enhancer();enhancer.setSuperclass(RealService.class);enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("CGLIB Proxy: before"); Object result = proxy.invokeSuper(obj, args); System.out.println("CGLIB Proxy: after"); return result; }});RealService proxy = (RealService) enhancer.create();proxy.doSomething();
CGLIB适用于更广泛的场景,尤其适合Spring这类框架中默认使用的代理机制。但要注意的是,不能代理final类和final方法。
Spring AOP中的代理机制:自动选择JDK或CGLIB
在实际开发中,我们经常使用Spring AOP来实现日志记录、事务管理等功能。Spring底层会根据目标类是否实现了接口来自动选择使用JDK动态代理还是CGLIB代理。
Spring的判断逻辑大致如下:
如果目标类实现了至少一个接口,优先使用JDK动态代理否则使用CGLIB代理
当然你也可以强制Spring始终使用CGLIB代理,只需在配置中设置:
或者在注解驱动下启用:
@EnableAspectJAutoProxy(proxyTargetClass = true)
这种机制让开发者不需要关心底层代理是如何构建的,只需要专注于切面逻辑的编写即可。
总的来说,Java中代理模式的实现方式各有适用场景。静态代理适合小规模项目或教学用途;JDK动态代理和CGLIB代理则更适合实际开发中灵活扩展的需求;而Spring在此基础上进一步封装,使得代理机制对开发者透明化。
基本上就这些。
以上就是Java中代理模式的几种实现方式详细技术解析的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/148312.html
微信扫一扫
支付宝扫一扫