- 浏览: 101495 次
- 性别:
- 来自: 武汉
-
最新评论
-
zljerityzljerity:
<#assign ipage=page?number&g ...
freeMark全解 -
qiankai86:
...
freeMark全解
网上的资料总是说spring的aop功能不支持对象内部方法间的嵌套代理。
不过今天试了一下,在不使用spring框架的时候,直接调用cglib的api,是可以实现一个对象内部方法间的嵌套代理的。
那么。。。为什么总说spring不支持一个实例方法间的嵌套代理呢。
如果强制spring使用cglib后可以实现嵌套代理,那么spring又是如何避免一个server内部方法间的事务的嵌套呢。
有点疑惑。。。望指点。。。:)
问题补充:
感谢netfork的关注,贴出cglib的测试代码,测试代码改自论坛中另外一个介绍cglib使用的帖子。
1)被代理类findInfo方法调用findInfo2方法
- package x.y.aop.cglib;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class StudentInfoServiceImpl {
- protected final Log logger = LogFactory.getLog(getClass());
- public void findInfo(String name){
- logger.info("你目前输入的名字是:"+name);
- //StudentInfoServiceImpl类内部调用!
- findInfo2();
- logger.info("complete method findInfo");
- }
- public void findInfo2(){
- logger.info("i'm in findinfo2!!!");
- }
- }
package x.y.aop.cglib; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class StudentInfoServiceImpl { protected final Log logger = LogFactory.getLog(getClass()); public void findInfo(String name){ logger.info("你目前输入的名字是:"+name); //StudentInfoServiceImpl类内部调用! findInfo2(); logger.info("complete method findInfo"); } public void findInfo2(){ logger.info("i'm in findinfo2!!!"); } }
2)cglib拦截类
- package x.y.aop.cglib;
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class AOPInstrumenter implements MethodInterceptor {
- protected final Log logger = LogFactory.getLog(getClass());
- private Enhancer enhancer = new Enhancer();
- public Object getInstrumentedClass(Class clz) {
- enhancer.setSuperclass(clz);
- enhancer.setCallback(this);
- return enhancer.create();
- }
- public Object intercept(Object o, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- logger.info("进入代理 方法:" + method.getName());
- logger.info("开始执行原始方法:" + method.getName());
- Object result = proxy.invokeSuper(o, args);
- logger.info("退出代理 方法:" + method.getName());
- return result;
- }
- }
package x.y.aop.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class AOPInstrumenter implements MethodInterceptor { protected final Log logger = LogFactory.getLog(getClass()); private Enhancer enhancer = new Enhancer(); public Object getInstrumentedClass(Class clz) { enhancer.setSuperclass(clz); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable { logger.info("进入代理 方法:" + method.getName()); logger.info("开始执行原始方法:" + method.getName()); Object result = proxy.invokeSuper(o, args); logger.info("退出代理 方法:" + method.getName()); return result; } }
3)main方法
- package x.y.aop.cglib;
- public class main {
- public static void main(String[] args) {
- AOPInstrumenter instrumenter = new AOPInstrumenter();
- StudentInfoServiceImpl studentInfo = (StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class);
- studentInfo.findInfo("阿飞");
- }
- }
package x.y.aop.cglib; public class main { public static void main(String[] args) { AOPInstrumenter instrumenter = new AOPInstrumenter(); StudentInfoServiceImpl studentInfo = (StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class); studentInfo.findInfo("阿飞"); } }
4)log日志输入
- main - 进入代理 方法:findInfo
- main - 开始执行原始方法:findInfo
- main - 你目前输入的名字是:阿飞
- main - 进入代理 方法:findInfo2
- main - 开始执行原始方法:findInfo2
- main - i'm in findinfo2!!!
- main - 退出代理 方法:findInfo2
- main - complete method findInfo
- main - 退出代理 方法:findInfo
main - 进入代理 方法:findInfo main - 开始执行原始方法:findInfo main - 你目前输入的名字是:阿飞 main - 进入代理 方法:findInfo2 main - 开始执行原始方法:findInfo2 main - i'm in findinfo2!!! main - 退出代理 方法:findInfo2 main - complete method findInfo main - 退出代理 方法:findInfo
采纳的答案
2009-01-04 netfork (初级程序员)
如果有一天google能搜到此篇文章,为了给寻找答案的人一个交待,在这里再补上一段。
经过昨天和楼主的讨论,总算把这个问题基本弄清楚了。
纯粹用CGLIB来代理时,确实会出现嵌套代理的情况,package/protected/public方法均可能互相嵌套。
但是通过Spring来借助于CGLIB实现AOP时,就不会出现嵌套代理的情况。
原因是Spring使用CGLIB时,只是用了一个代理的壳,来达到同JDK代理同样的效果,在调用目标对象的虚拟子类对象的方法时,通过回调方法,实际上还是调用的目标对象的真身,并没有调用子类对象的父类方法,由于调用的是目标对象(实实在在的对象)的方法,所以在这个方法里再次调用其他方法时,就不会被代理到了,因此就不会产生嵌套代理的情况。
关于AOP的CGLIB的较完整的分析过程,可以参照下面的分析。
http://netfork.iteye.com/blog/286215
经过昨天和楼主的讨论,总算把这个问题基本弄清楚了。
纯粹用CGLIB来代理时,确实会出现嵌套代理的情况,package/protected/public方法均可能互相嵌套。
但是通过Spring来借助于CGLIB实现AOP时,就不会出现嵌套代理的情况。
原因是Spring使用CGLIB时,只是用了一个代理的壳,来达到同JDK代理同样的效果,在调用目标对象的虚拟子类对象的方法时,通过回调方法,实际上还是调用的目标对象的真身,并没有调用子类对象的父类方法,由于调用的是目标对象(实实在在的对象)的方法,所以在这个方法里再次调用其他方法时,就不会被代理到了,因此就不会产生嵌套代理的情况。
关于AOP的CGLIB的较完整的分析过程,可以参照下面的分析。
http://netfork.iteye.com/blog/286215
发表评论
-
ofbiz 之entity实体
2014-03-25 18:16 955ofbiz 之entity实体 1. 实体定义文件 实体定 ... -
ofbiz迷你语言
2012-08-08 17:13 2310simple-map-processor 和 sim ... -
ofbiz之entity 实体解析
2012-08-08 17:12 1525ofbiz 之entity实体 1. 实体定义文件 实体定 ... -
ofbiz之旅-实体简介(中英译)
2012-08-09 09:34 1183OFBIZ ENTITY ENGINE COOKBOOK = ... -
OFBIz之旅[结构]
2012-08-08 17:03 1505OFBIz之旅[结构] 注意: 1,持久层,在OFBI ... -
java concurrent 探秘(2)
2011-08-08 14:21 927java concurrent 探秘(2) Blo ... -
java concurrent 探秘
2011-08-08 11:02 828java concurrent 探秘 我们都知道,在JD ... -
one-to-one 一对一主键关联映射_单向
2011-08-03 17:22 1337one-to-one 一对一主键关联映射_单向 一对一主键关 ... -
JavaScript验证正则表达式大全
2011-07-27 17:18 934上篇文章《JavaScript验证正则表达式大全》说的是jav ... -
JavaScript验证正则表达式大全
2011-07-27 17:17 842JavaScript验证正则表达式大全 JavaScript验 ... -
js 收集1
2011-01-14 09:49 10741.javascript的数组API Js代码 ... -
struts 核心解析
2010-12-03 14:25 2467一、概述 Struts2的核心是一个Fil ... -
Java类库中的集合类解析
2010-11-29 16:05 1098这篇我准备从源码的高度来看看集合中各个实现类的是如何组织我们存 ... -
jboss classloader机制以及scope配置
2010-11-29 15:06 17261. 概念介绍 UCL : org.jboss.mx. ... -
总结和对比一下(jboss,tomcat,jetty)容器的classloader机制
2010-11-29 14:58 1999总结和对比一下(jboss,tomcat,je ... -
jboss,tomcat,jetty 容器的classloader机制
2010-11-29 14:53 4602背景 前段时间一直在做应用容器的迁移,将公司的应用 ... -
Session,Cookie,jsessionid和Url重写
2010-11-29 12:55 1940Session,Cookie,jsessionid ... -
DWR work
2010-11-25 18:14 902这段时间较闲,研究了一 ... -
CXF jaxws spring configuration
2010-11-19 16:27 1608最近在cxf-zh中有人问及了有关Spring配置CXF Cl ... -
线程安全总结2
2010-11-17 16:48 830站内很多人都问我,所谓线程的“工作内存”到底是个什么东西? ...
相关推荐
- **初始化性能**:CGLIB 在创建代理对象时可能较慢,但在运行时可能更快。 - **适用性**:如果目标类实现了接口,优先考虑 JDK 动态代理;如果没有实现接口,则使用 CGLIB 动态代理。 - **最终选择**:根据实际应用...
4. **MethodProxy**:CGLib生成的代理对象会包含一个MethodProxy实例,这个对象可以调用实际的方法。在MethodInterceptor的`intercept`方法中,我们可以通过MethodProxy来调用目标方法。 5. **代理对象的创建**:...
AOP的实现基于动态代理技术,动态代理可以在程序运行时为目标对象创建代理对象,代理对象通常会增加目标对象的功能。 动态代理有两种实现方式: - **JDK动态代理**:适用于目标对象实现了接口的情况,通过`Proxy....
当调用一个接口方法时,JDK动态代理会在运行时创建一个代理类,该类继承了Proxy类并实现了被代理的接口。通过Proxy类中的newProxyInstance方法,可以生成代理对象,其内部实现依赖于实现了InvocationHandler接口的...
Spring AOP 使用了两种代理机制来实现:基于 JDK 的动态代理和基于 CGLib 的动态代理。JDK 动态代理只支持接口的代理,而不支持类的代理。CGLib 采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用...
Spring会创建一个代理对象来包裹被注解的方法,当调用这些方法时,实际上是在调用代理对象,从而实现事务的自动化管理。 在事务管理过程中,Spring通过`@EnableAspectJAutoProxy`注解启用AOP代理。AOP代理可以是JDK...
Spring 3.1 是一个重要的Java应用程序框架,主要用于构建企业级的、基于组件的、松散耦合的应用程序。这个框架以其灵活性、可扩展性和强大的功能而闻名,它支持多种编程模型,包括依赖注入(Dependency Injection,...
7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理...
通过对以上知识点的深入探讨,我们可以看到 Spring Framework 不仅仅是一个简单的框架,而是集成了许多先进设计理念和技术的综合平台。无论是对于初学者还是资深开发者而言,掌握这些核心概念都是非常必要的。
- **AOP 代理** (AOP Proxy): 实现 AOP 的关键,Spring 使用 JDK 动态代理或 CGLIB 代理来实现。 #### 六、属性编辑器、数据绑定、校验与 BeanWrapper - **属性编辑器** (Property Editor): 用于转换不可直接转换...
7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”通知器 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...
7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”通知器 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...
- Spring AOP主要通过代理机制实现,支持JDK动态代理和CGLIB代理两种方式。对于实现了接口的类,默认使用JDK动态代理;对于没有实现接口的类,则使用CGLIB代理。 #### 三、BeanWrapper:属性操作的抽象层 ...
事务传播行为是指在一个已存在的事务中调用另一个方法时,如何处理这两个方法间的事务关系。Spring提供了多种不同的事务传播行为选项,以便开发者能够更灵活地控制事务的范围。 #### 传播行为类型: 1. **...
Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...
动态代理是Java提供的一种机制,它允许我们在运行时创建一个代理类来代理目标对象,从而在不修改原有代码的情况下,增加额外的功能。在事务管理中,动态代理通常用于实现AOP(面向切面编程),将事务逻辑与业务逻辑...
7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...
7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动...
Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。 Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...
在Spring中,当目标类没有实现任何接口时,Spring会使用CGLIB创建代理对象来实现AOP的功能,包括事务管理。CGLIB代理通过继承目标类并在运行时动态生成子类,从而实现方法拦截和事务控制。 在SSM中,事务管理主要...