JDK代理、CGLIB代理及静态代理
发布日期:2021-04-30 21:00:27
浏览次数:171
分类:精选文章
本文共 5057 字,大约阅读时间需要 16 分钟。
代理模式详解
代理模式定义
在软件设计中,代理模式是一种常用的设计模式。其核心思想是:通过引入一个代理类,间接地代理目标对象的操作。代理类与被代理类(目标对象)通常都实现同一个接口或继承自同一个基类。代理类中存有指向被代理类的引用。当通过代理类的方法调用时,实际执行的是被代理类对应的方法。
代理的分类
代理模式可根据实现方式分为以下几种:
静态代理
静态代理是软件开发中最常用的代理形式。在代码中显式地定义了代理类。这种方式通常用于需求明确、结构清晰的场景。JDK代理
JDK动态代理(Java Development Kit Proxy)是基于Java反射机制实现的动态代理。其特点是只能对实现了Java接口的类生成代理,而不能针对类本身。CGLIB代理
CGLIB(Code Generation Library)代理是基于ASM字节码生成框架实现的动态代理。它通过动态生成目标类的子类来实现代理功能。这种方式适用于需要对类进行继承处理的情况。代码实现
整体代码目录结构
以下是完整代码实现示例:
com/ xszr/ proxy/ static/ ICount.java CountImpl.java CountProxyImpl.java StaticMain.java jdk/ ICount.java CountImpl.java MyInvocationHandler.java JDKMain.java cglib/ ICount.java CountImpl.java CountImplCglib.java CGLIBMain.java
静态代理实现
ICount.java
package com.xzsyr.statiz.proxy;public interface ICount { void queryCount();} CountImpl.java
package com.xzsyr.statiz.proxy;public class CountImpl implements ICount { @Override public void queryCount() { System.out.println("我是queryCount方法。"); }} CountProxyImpl.java
package com.xzsyr.statiz.proxy;public class CountProxyImpl implements ICount { private CountImpl count; public CountProxyImpl(CountImpl count) { super(); this.count = count; } @Override public void queryCount() { System.out.println("事务处理前....."); count.queryCount(); System.out.println("事务处理后....."); }} StaticMain.java
package com.xzsyr.statiz.proxy;public class StaticMain { public static void main(String[] args) { CountImpl c = new CountImpl(); CountProxyImpl p = new CountProxyImpl(c); p.queryCount(); }} JDK代理实现
ICount.java
package com.xzsyr.jdkdy.proxy;public interface ICount { void queryCount();} CountImpl.java
package com.xzsyr.jdkdy.proxy;public class CountImpl implements ICount { @Override public void queryCount() { System.out.println("我是queryCount方法"); }} MyInvocationHandler.java
package com.xzsyr.jdkdy.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler { private CountImpl countImpl; public MyInvocationHandler(CountImpl countImpl) { this.countImpl = countImpl; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("事务处理前。。。。"); method.invoke(countImpl, args); System.out.println("事务处理后。。。。"); return null; }} JDKMain.java
package com.xzsyr.jdkdy.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class JDKMain { public static void main(String[] args) { CountImpl count = new CountImpl(); count.queryCount(); System.out.println("=========================================="); InvocationHandler hander = new MyInvocationHandler(count); ICount proxyInstance = (ICount) Proxy.newProxyInstance(count.getClass().getClassLoader(), count.getClass().getInterfaces(), hander); proxyInstance.queryCount(); }} CGLIB代理实现
ICount.java
package com.xzsyr.cglibdy.proxy;public class ICount { public void queryCount() { System.out.println("账户类查询方法"); }} CountImpl.java
package com.xzsyr.cglibdy.proxy;public class CountImpl { public void quryCount() { System.out.println("查询querycount方法"); }} CountImplCglib.java
package com.xzsyr.cglibdy.proxy;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CountImplCglib implements MethodInterceptor { private Object target; public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("预处理——————"); proxy.invokeSuper(obj, args); System.out.println("调用后操作——————"); return null; }} CGLIBMain.java
package com.xzsyr.cglibdy.proxy;public class CGLIBMain { public static void main(String[] args) { CountImpl c = new CountImpl(); CountImplCglib cglib = new CountImplCglib(); CountImpl ccglib = (CountImpl) cglib.getInstance(c); ccglib.quryCount(); }} 代理模式的选择依据
在实际应用中,选择使用哪种代理方式取决于具体需求:
静态代理 vs 动态代理
- 静态代理:显式定义代理类,适合需求明确且结构清晰的场景。
- 动态代理:通过反射或字节码生成动态生成代理类,适合需求变化多端、对具体实现细节不敏感的场景。
JDK代理 vs CGLIB代理
- JDK代理:适用于目标对象实现了接口的情况。
- CGLIB代理:适用于目标对象是具体类且需要继承处理的情况。
Spring的选择依据
- Spring默认会根据目标Bean是否实现接口选择JDK或CGLIB代理。
- 可以通过配置强制使用CGLIB代理:
CGLIB的使用注意事项
依赖包
使用CGLIB时,需要引入以下依赖:net.sf.cglib cglib 3.1 org.ow2.asm asm 5.0.4 错误处理
如果在非Maven项目中使用CGLIB,需要手动引入cglib.jar和asm.jar文件。性能对比
相比JDK代理,CGLIB的性能略低,但在高并发场景下表现更优。
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2026年06月05日 05时07分19秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
pip 无法从 requirements.txt 安装软件包
2023-03-02
pip/pip3更换国内源
2023-03-02
pip3 install PyQt5 --user 失败
2023-03-02
pip3命令全解析:Python3包管理工具的详细使用指南
2023-03-02
PIPE 接口信号列表
2023-03-02
pipeline配置与管理Job企业级实战
2023-03-02
pipeline项目配置实战
2023-03-02
Pipenv 与 Conda?
2023-03-02
QVGA/HVGA/WVGA/FWVGA分辨率屏含义及大小//Android虚拟机分辨率
2023-03-02
pipy国内镜像的网址
2023-03-02
quiver绘制python语言
2023-03-02
pip下载缓慢
2023-03-02
PIP使用SSH从BitBucket安装自定义软件包,无需输入SSH密码
2023-03-02
pip在安装模块时提示Read timed out
2023-03-02
pip更换源
2023-03-02
SpringBoot之Banner源码深度分解
2023-03-02