🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞
💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论
🔥🔥🔥(源码 + 调试运行 + 问题答疑)🔥🔥🔥 有兴趣可以联系我
🔥🔥🔥 文末有往期免费源码,直接领取获取(无删减,无套路)
CGLIB代理:MyBatis中的备选引擎
-
《MyBatis代理双引擎:JDK动态代理与CGLIB的技术选型》
-
《超越接口限制:CGLIB如何为MyBatis提供类代理能力》
-
《手写MyBatis高级篇:CGLIB代理实现懒加载黑科技》
-
《无接口也能代理!CGLIB在MyBatis插件中的应用揭秘》
-
《动态代理终极对决:JDK Proxy vs CGLIB的MyBatis实践》
CGLIB代理:MyBatis中的备选引擎
引言: 当JDK动态代理遇到无接口的类,CGLIB闪亮登场。本文通过手写CGLIB代理,揭示MyBatis在懒加载和插件系统中的类代理技术。
一、CGLIB核心组件解析
组件 | 作用 | 对应JDK代理 |
---|---|---|
Enhancer | 代理生成器 | Proxy |
MethodInterceptor | 方法拦截器 | InvocationHandler |
CallbackFilter | 回调过滤器 | 无直接对应 |
二、CGLIB代理实战:为User类增强
// 1. 引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
// 2. 创建方法拦截器
public class LogInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
System.out.println("【CGLIB拦截】方法: " + method.getName());
// 不拦截toString方法
if ("toString".equals(method.getName())) {
return proxy.invokeSuper(obj, args);
}
// 模拟数据库懒加载
if ("getPosts".equals(method.getName())) {
System.out.println("触发懒加载...");
return Collections.singletonList(new Post("CGLIB代理的帖子"));
}
return proxy.invokeSuper(obj, args);
}
}
// 3. 生成代理对象
public class CglibProxyFactory {
public static <T> T createProxy(Class<T> targetClass) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(new LogInterceptor());
return (T) enhancer.create();
}
}
// 4. 客户端调用
public class Client {
public static void main(String[] args) {
// 代理普通类(非接口!)
User userProxy = CglibProxyFactory.createProxy(User.class);
System.out.println("代理类: " + userProxy.getClass());
System.out.println("父类: " + userProxy.getClass().getSuperclass());
// 触发拦截
List<Post> posts = userProxy.getPosts();
System.out.println(posts.get(0).getTitle());
}
}
控制台输出:
代理类: class com.example.User$$EnhancerByCGLIB$$a1b2c3d4
父类: class com.example.User
【CGLIB拦截】方法: getPosts
触发懒加载...
CGLIB代理的帖子
三、CGLIB代理原理剖析
字节码生成过程:
-
继承目标类生成子类
-
重写非final方法
-
方法中调用MethodInterceptor
-
通过FastClass机制加速调用
四、MyBatis中的代理技术选型
JDK代理 vs CGLIB 对比
特性 | JDK动态代理 | CGLIB |
---|---|---|
代理对象 | 实现接口 | 继承目标类 |
速度 | 调用快 | 生成快 |
限制 | 需接口 | 无法代理final类/方法 |
依赖 | JVM内置 | 第三方库 |
MyBatis的代理策略
-
Mapper接口:JDK动态代理(100%) 因为Mapper都是接口,JDK代理最合适
-
懒加载:CGLIB代理(可选)
// 配置开启CGLIB懒加载代理 <setting name="lazyLoadingEnabled" value="true"/> <setting name="proxyFactory" value="CGLIB"/>
-
插件系统:CGLIB特殊应用 某些插件需要代理目标对象本身
五、CGLIB实战:手写懒加载代理
public class LazyLoaderInterceptor implements MethodInterceptor {
private volatile boolean loaded = false;
private Object realValue;
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
// 触发加载条件:首次调用getter方法
if (method.getName().startsWith("get") && !loaded) {
synchronized (this) {
if (!loaded) {
System.out.println("【CGLIB】执行数据库查询...");
realValue = loadFromDatabase(); // 实际数据库操作
loaded = true;
}
}
}
return loaded ? method.invoke(realValue, args) : null;
}
}
结语: CGLIB作为JDK动态代理的重要补充,为MyBatis提供了处理非接口代理的能力。虽然在Mapper代理中不是主角,但在懒加载等高级特性中发挥着不可替代的作用,展现了MyBatis灵活的技术选型智慧。
往期免费源码 (无删减,无套路):🔥🔥🔥
https://pan.baidu.com/s/1sjAr08PU9Xe7MQf1gjGM5w?pwd=6666
「在线考试系统源码(含搭建教程)」 (无删减,无套路):🔥🔥🔥
链接:https://pan.quark.cn/s/96c4f00fdb43 提取码:WR6M
往期免费源码对应视频:
免费获取--SpringBoot+Vue宠物商城网站系统
🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞
💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论
🔥🔥🔥(源码 + 调试运行 + 问题答疑)
🔥🔥🔥 有兴趣可以联系我