CGLIB 实现代理对象API
转载自 CGLIB 实现代理对象API
1. 加入库 |
cglib库 cglib-2.2.jar asm库(cglib 需要asm库,如果没有加入asm的jar文件,就会报asm错误) asm-3.1.jar |
2. 定义CGLIB操作类 |
package com.machome.cglibtest; import java.lang.reflect.Method; public class CGlibProxyFactory implements MethodInterceptor { public Object createProxyInstance(Object targetObject){ |
3.测试代码 |
测试代码: CGlibProxyFactory factory = new CGlibProxyFactory(); StuService bean = (StuService)factory.createProxyInstance( new StuService()); List<Stu> stuList = bean.findAll(); if(stuList!=null){ for(Stu temp:stuList) System.out.println(temp.getId()+":"+temp.getName()); System.out.println("finished"); 执行结果: |
cglib 执行intercept()的原理:
- 自定义类应该实现MethodInterceptor接口,,覆写 intercept()方法
public interface MethodInterceptor extends Callback { public abstract Object intercept(Object obj, Method method, Object aobj[], MethodProxy methodproxy) throws Throwable; } |
- Enhancer对象设其Callback对象(实际是Callbacks对象,一个数组,但我们经常只设一个)
enhancer.setCallback(Callback callback); |
- 这样当Enhancer对象建立代理对象的时候,就会在执行用户调用的方法前,先执行intercept()方法
常见的两种不同的实现MethodInterceptor接口的cglib编程
- 1.自定义类直接实现MethodInterceptor接口,覆写 intercept()方法
public class CGlibProxyFactory implements MethodInterceptor { public Object createProxyInstance(Object targetObject){ ... enhancer.setCallback(this); ... } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { ... } } |
- 2.另一种方式,定义一个内部类,该类实现MethodInterceptor接口,覆写intercept()方法
public class CGlibProxyFactory1 {
public Object createProxyInstance(Object targetObject){ private class MethodInterceptorImpl implements MethodInterceptor { @Override |
注意 public Object intercept(Object obj, Method method, Object[] aobj,MethodProxy methodproxy)方法的第一个参数obj有很大问题
intercept方法里的主要动作是执行invoke方法
有两种执行方法:
法1: |
将参数obj传入invokeSuper()方法: return methodproxy.invokeSuper(obj, aobj); obj应该是传入Enhancer 对象的用户对象 |
法2: |
或者将传入Enhancer对象前的原始用户对象传入invoke()方法: return methodproxy.invoke(targetObject, aobj); |
实际工作中发现,参数obj不态好用. 如果你想intercept()方法中调用对象执行一些方法的话,obj会出stackOverflow这样的异常
如下面的例子:
public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable { StuService bean = (StuService)obj; Object result = null; if(!method.getName().equals("save")&&(bean.findAll().size()==0)) { // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警 System.out.println("list is null,method is stoped"); }else{ result = methodproxy.invokeSuper(obj, aobj); } return result; } |
执行时会出线面的异常: Exception in thread "main" java.lang.StackOverflowError |
改成下面就好了: public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable { StuService bean = (StuService)this.targetObject; //从外部传入的原始用户实例 Object result = null; if(!method.getName().equals("save")&&(bean.findAll().size()==0)) { // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警 System.out.println("list is null,method is stoped"); }else{ result = methodproxy.invoke(targetObject, aobj); } return result; } |
cglib 在 spring,hibernate中的应用
Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制
Spring则是利用cglib来实现动态代理。
spring,hibernate同时支持proxy类动态代理和cglib,二者的区别
proxy动态代理只能对 实现了接口 的类生成代理,而不能针对类
CGLIB是针对类生成代理,主要是对用户类生成一个子类
spring 下缺省是支持proxy 动态代理,如何强制使用CGLIB生成代理?
spring 主要在两个地方使用代理
AOP: <aop:aspectj-autoproxy proxy-target-class="true"/> |
Transaction: <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> |
1. 加入库 |
cglib库 cglib-2.2.jar asm库(cglib 需要asm库,如果没有加入asm的jar文件,就会报asm错误) asm-3.1.jar |
2. 定义CGLIB操作类 |
package com.machome.cglibtest; import java.lang.reflect.Method; public class CGlibProxyFactory implements MethodInterceptor { public Object createProxyInstance(Object targetObject){ |
3.测试代码 |
测试代码: CGlibProxyFactory factory = new CGlibProxyFactory(); StuService bean = (StuService)factory.createProxyInstance( new StuService()); List<Stu> stuList = bean.findAll(); if(stuList!=null){ for(Stu temp:stuList) System.out.println(temp.getId()+":"+temp.getName()); System.out.println("finished"); 执行结果: |
cglib 执行intercept()的原理:
- 自定义类应该实现MethodInterceptor接口,,覆写 intercept()方法
public interface MethodInterceptor extends Callback { public abstract Object intercept(Object obj, Method method, Object aobj[], MethodProxy methodproxy) throws Throwable; } |
- Enhancer对象设其Callback对象(实际是Callbacks对象,一个数组,但我们经常只设一个)
enhancer.setCallback(Callback callback); |
- 这样当Enhancer对象建立代理对象的时候,就会在执行用户调用的方法前,先执行intercept()方法
常见的两种不同的实现MethodInterceptor接口的cglib编程
- 1.自定义类直接实现MethodInterceptor接口,覆写 intercept()方法
public class CGlibProxyFactory implements MethodInterceptor { public Object createProxyInstance(Object targetObject){ ... enhancer.setCallback(this); ... } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { ... } } |
- 2.另一种方式,定义一个内部类,该类实现MethodInterceptor接口,覆写intercept()方法
public class CGlibProxyFactory1 {
public Object createProxyInstance(Object targetObject){ private class MethodInterceptorImpl implements MethodInterceptor { @Override |
注意 public Object intercept(Object obj, Method method, Object[] aobj,MethodProxy methodproxy)方法的第一个参数obj有很大问题
intercept方法里的主要动作是执行invoke方法
有两种执行方法:
法1: |
将参数obj传入invokeSuper()方法: return methodproxy.invokeSuper(obj, aobj); obj应该是传入Enhancer 对象的用户对象 |
法2: |
或者将传入Enhancer对象前的原始用户对象传入invoke()方法: return methodproxy.invoke(targetObject, aobj); |
实际工作中发现,参数obj不态好用. 如果你想intercept()方法中调用对象执行一些方法的话,obj会出stackOverflow这样的异常
如下面的例子:
public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable { StuService bean = (StuService)obj; Object result = null; if(!method.getName().equals("save")&&(bean.findAll().size()==0)) { // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警 System.out.println("list is null,method is stoped"); }else{ result = methodproxy.invokeSuper(obj, aobj); } return result; } |
执行时会出线面的异常: Exception in thread "main" java.lang.StackOverflowError |
改成下面就好了: public Object intercept(Object obj, Method method, Object[] aobj, MethodProxy methodproxy) throws Throwable { StuService bean = (StuService)this.targetObject; //从外部传入的原始用户实例 Object result = null; if(!method.getName().equals("save")&&(bean.findAll().size()==0)) { // 如果方法名不是save,而实例的列表为空,就不执行方法,而是告警 System.out.println("list is null,method is stoped"); }else{ result = methodproxy.invoke(targetObject, aobj); } return result; } |
cglib 在 spring,hibernate中的应用
Hibernate主要是利用cglib生成pojo的子类并override get方法来实现lazy loading机制
Spring则是利用cglib来实现动态代理。
spring,hibernate同时支持proxy类动态代理和cglib,二者的区别
proxy动态代理只能对实现了接口的类生成代理,而不能针对类
CGLIB是针对类生成代理,主要是对用户类生成一个子类
spring 下缺省是支持proxy 动态代理,如何强制使用CGLIB生成代理?
spring 主要在两个地方使用代理
AOP: <aop:aspectj-autoproxy proxy-target-class="true"/> |
Transaction: <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> |
CGLIB 实现代理对象API相关推荐
- 使用cglib创建代理对象
在上一篇文章中,我讨论了基于标准Java的代理对象. 当您要在实现接口的对象上具有方法调用处理程序时,可以使用这些方法. Java反射代理的创建要求您具有一个实现接口的对象. 我们要代理的对象已经失控 ...
- CGLIB动态代理对象执行流程分析
前言 都说CGLIB动态代理对象执行方法的速度相较于JDK动态代理更快,那么为什么更快,实际是因为CGLIB中采用了FastClass机制,本篇文章将对CGLIB动态代理对象执行某一个方法的流程进行分 ...
- cglib创建代理对象(1)
cglib创建代理对象 还是从一个的小demo开始 例子 被代理的类 public class Bean{public String sayHello(String name) {return &qu ...
- 使用djcproxy创建代理对象
在过去的几周中,我展示了如何使用Java Reflection API和cglib创建代理对象. 在本文中,我将向您展示如何使用djcproxy做到这一点. 哦,不是,另一个代理实现! 除了我创建此代 ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- SpringAOP的CGLIB动态代理的底层原理实现
欢迎加入java学习讨论群:725562382 CGLIB动态代理: CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以 ...
- Java 静态代理、Java动态代理、CGLIB动态代理
为什么80%的码农都做不了架构师?>>> Java 的代理就是客户类不再直接和委托类打交道, 而是通过一个中间层来访问, 这个中间层就是代理.为啥要这样呢, 是因为使用代理有 ...
- CGLIb 创建代理
CGLIb 创建代理 创建回调 创建代理(通过增强器和回调接口) 设置回调 CGLib总结 代理对象通过继承目标对象来封装目标对象的实现 CGlib 拦截的实现--在执行目标方法前判断拦截器是否存在并 ...
- 谁与争锋,JDK动态代理大战CGLib动态代理
文章目录 一.前言 二.基本概念 三.JDK 和 CGLib动态代理区别 3.1 JDK动态代理具体实现原理 3.2 CGLib动态代理 3.3 两者对比 3.4 使用注意 四.JDK 和 CGLib ...
最新文章
- 04-c#入门(类型转换)
- 该项研究降低了使用大脑信号控制机器人手臂的位置误差
- cocos2dx环境搭建(android平台)
- 数据中心气流管理的基础:密闭系统的比较
- Tensorflow模型的保存与恢复的细节
- 程序员面试金典 - 面试题 16.10. 生存人数(自定义优先队列)
- Hyper-V实战:高可用性-配置Hyper-V群集
- java学习笔记------ PrintStream
- psp模拟器完美字库_安卓PSP模拟器评测:讨鬼传
- BZOJ 2145 悄悄话
- 幼儿园小程序实战开发教程
- 超全面Figma,Pixso和Sketch工具盘点
- 破解Esxi服务器中Windows虚机密码(Esxi服务器Windows虚拟机忘记密码解决方案)
- 苹果cms新手入门安装配置教程
- 面对人工智能,我们应有的态度
- js 事件绑定传入自定义参数
- HTML设计网页之网页头部
- PostgreSQL入门之基本工具+常用psql命令+show语法
- Linux中./configure文件配置详解
- open /run/flannel/subnet.env: no such file or directory
热门文章
- php防止cc攻击代码,防cc攻击PHP防CC攻击实现代码
- 广州计算机专业王健,王健-计算机与信息工程学院
- 基于matlab的数字下变频器的设计与仿真应用,基于MATLAB的数字下变频器的没汁与仿真应用...
- python和qt哪个好_做个小的桌面用node还是QT比较好? - Web开发 - WebDev - 水木社区...
- 判别学习与生成学习的区别
- 相同类方法之间调用,注解失效的问题
- 利用Arthas排查NoSuchMethodError
- ABC 189 E - Rotate and Flip 矩阵转移
- CF1497E2 Square-free division (hard version)
- 牛客题霸 [没有重复项数字的所有排列] C++题解/答案