0 0

spring基于cglib实现aop时是否可以支持一个对象内部方法间的嵌套代理10

问答哪里没有人理,放在这里试试吧。。。

悬赏:5 发布时间:2008-12-31 提问人:jef (初级程序员)

网上的资料总是说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!!!");
	}
	
	
}


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;
	}

}


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("阿飞");
	}
}


4)log日志输入
main - 进入代理 方法:findInfo
main - 开始执行原始方法:findInfo
main - 你目前输入的名字是:阿飞
main - 进入代理 方法:findInfo2
main - 开始执行原始方法:findInfo2
main - i'm in findinfo2!!!
main - 退出代理 方法:findInfo2
main - complete method findInfo
main - 退出代理 方法:findInfo


这个测试可以说明cglib能实现同一对象方法级的嵌套拦截了吧
2009年1月03日 11:57

4个答案 按时间排序 按投票排序

0 0

采纳的答案

如果有一天google能搜到此篇文章,为了给寻找答案的人一个交待,在这里再补上一段。
经过昨天和楼主的讨论,总算把这个问题基本弄清楚了。
纯粹用CGLIB来代理时,确实会出现嵌套代理的情况,package/protected/public方法均可能互相嵌套。
但是通过Spring来借助于CGLIB实现AOP时,就不会出现嵌套代理的情况。
原因是Spring使用CGLIB时,只是用了一个代理的壳,来达到同JDK代理同样的效果,在调用目标对象的虚拟子类对象的方法时,通过回调方法,实际上还是调用的目标对象的真身,并没有调用子类对象的父类方法,由于调用的是目标对象(实实在在的对象)的方法,所以在这个方法里再次调用其他方法时,就不会被代理到了,因此就不会产生嵌套代理的情况。

关于AOP的CGLIB的较完整的分析过程,可以参照下面的分析。
http://netfork.iteye.com/blog/286215

2009年1月04日 00:12
0 0

刚刚看了补充,跟我想的一致的,果然是public方法调本类的public方法,这种程序,一般是很少碰到的,如果出现,应该是设计的问题。而且public方法调本类public方法,在事务处理中就更难发生了。

总结:楼主举的案例确实是会存在嵌套的情况,但真实的系统设计中,不会出现这种情况。分层结构和通常系统的设计思路,完全可以避免掉这种情况的出现。

2009年1月03日 12:40
0 0

似乎有点理解楼主的意思了。
下面的文章有说到动态代理情况下的AOP是不支持嵌套代理的。

http://www.iteye.com/topic/40553

该文中也隐约提到了CGLIB代理的情况。根据我的理解(不定对不对,我只是前段Debug个Spring和CBLIB的源码,有段时间了,也没功夫再Debug了),如果换作CGLIB,CGLIB会虚拟一个子类作为代理对象,这个虚拟生成的子类中肯定会重截所有的public方法,package/protected的,我不太清楚,private的方法没有重载的必要。如果想彻底弄明白,只要Debug个一下Spring和CGLIB的源码应该就能弄清楚。
这样的话,如果你是在public方法中调public方法,通过AOP以后,调用过程就是这样的:
子类(CGLIB的虚拟生成类)方法A->父类(实际类)方法A->子类方法B->父类方法B
从这个过程来看,你所谓的AOP嵌套肯定会发生的,因为在父类方法B被子类的方法B代理过了。

上文分析只是public方法时发生的情况,通常情况下,public方法再调用本类中的public方法的可能性并不大,如果存在,也可能是设计上的问题。
所以,从这个意义上讲,只要public方法中调用的不是public方法方法留给楼主验证了(package/protected),事务的嵌套不可能会发生;而且即使是事务aop,也只是对特殊命名的方法进行事务控制,而不会是所有的方法都需要事务控制吧。所以,事务嵌套的情况是完全可以避免的。

2009年1月03日 12:29
0 0

楼主说的“对象内部方法”是指的私有方法吗?
能不能把测试的代码贴上来看看?大家一起研究下。

2009年1月03日 11:57

相关推荐

    spring隔离级别和aop基础.md

    - **初始化性能**:CGLIB 在创建代理对象时可能较慢,但在运行时可能更快。 - **适用性**:如果目标类实现了接口,优先考虑 JDK 动态代理;如果没有实现接口,则使用 CGLIB 动态代理。 - **最终选择**:根据实际应用...

    cglib 动态代理

    4. **MethodProxy**:CGLib生成的代理对象会包含一个MethodProxy实例,这个对象可以调用实际的方法。在MethodInterceptor的`intercept`方法中,我们可以通过MethodProxy来调用目标方法。 5. **代理对象的创建**:...

    Spring基础.pdf

    AOP的实现基于动态代理技术,动态代理可以在程序运行时为目标对象创建代理对象,代理对象通常会增加目标对象的功能。 动态代理有两种实现方式: - **JDK动态代理**:适用于目标对象实现了接口的情况,通过`Proxy....

    Spring学习思维笔记.pdf

    当调用一个接口方法时,JDK动态代理会在运行时创建一个代理类,该类继承了Proxy类并实现了被代理的接口。通过Proxy类中的newProxyInstance方法,可以生成代理对象,其内部实现依赖于实现了InvocationHandler接口的...

    深入理解Spring声明式事务:源码分析与应用实践

    Spring会创建一个代理对象来包裹被注解的方法,当调用这些方法时,实际上是在调用代理对象,从而实现事务的自动化管理。 在事务管理过程中,Spring通过`@EnableAspectJAutoProxy`注解启用AOP代理。AOP代理可以是JDK...

    spring3.1帮助文档

    Spring 3.1 是一个重要的Java应用程序框架,主要用于构建企业级的、基于组件的、松散耦合的应用程序。这个框架以其灵活性、可扩展性和强大的功能而闻名,它支持多种编程模型,包括依赖注入(Dependency Injection,...

    Spring-Reference_zh_CN(Spring中文参考手册)

    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. 使用“自动代理...

    SpringFramework常见知识点.md

    通过对以上知识点的深入探讨,我们可以看到 Spring Framework 不仅仅是一个简单的框架,而是集成了许多先进设计理念和技术的综合平台。无论是对于初学者还是资深开发者而言,掌握这些核心概念都是非常必要的。

    Spring 开发参考手册

    - **AOP 代理** (AOP Proxy): 实现 AOP 的关键,Spring 使用 JDK 动态代理或 CGLIB 代理来实现。 #### 六、属性编辑器、数据绑定、校验与 BeanWrapper - **属性编辑器** (Property Editor): 用于转换不可直接转换...

    Spring中文帮助文档

    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 API

    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 2.0 开发参考手册

    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 的魅力

    - Spring AOP主要通过代理机制实现,支持JDK动态代理和CGLIB代理两种方式。对于实现了接口的类,默认使用JDK动态代理;对于没有实现接口的类,则使用CGLIB代理。 #### 三、BeanWrapper:属性操作的抽象层 ...

    Spring.3.x企业应用开发实战(完整版).part2

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    java事务 - 使用动态代理

    动态代理是Java提供的一种机制,它允许我们在运行时创建一个代理类来代理目标对象,从而在不修改原有代码的情况下,增加额外的功能。在事务管理中,动态代理通常用于实现AOP(面向切面编程),将事务逻辑与业务逻辑...

    spring chm文档

    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.x企业应用开发实战(完整版) part1

    Spring3.0是Spring在积蓄了3年之久后,隆重推出的一个重大升级版本,进一步加强了Spring作为Java领域第一开源平台的翘楚地位。  Spring3.0引入了众多Java开发者翘首以盼的新功能和新特性,如OXM、校验及格式化框架...

    SSM事务管理所需jar包

    在Spring中,当目标类没有实现任何接口时,Spring会使用CGLIB创建代理对象来实现AOP的功能,包括事务管理。CGLIB代理通过继承目标类并在运行时动态生成子类,从而实现方法拦截和事务控制。 在SSM中,事务管理主要...

Global site tag (gtag.js) - Google Analytics