`
talentkep
  • 浏览: 101495 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

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

    博客分类:
阅读更多

网上的资料总是说spring的aop功能不支持对象内部方法间的嵌套代理。
不过今天试了一下,在不使用spring框架的时候,直接调用cglib的api,是可以实现一个对象内部方法间的嵌套代理的。
那么。。。为什么总说spring不支持一个实例方法间的嵌套代理呢。
如果强制spring使用cglib后可以实现嵌套代理,那么spring又是如何避免一个server内部方法间的事务的嵌套呢。
有点疑惑。。。望指点。。。:)
问题补充:
感谢netfork的关注,贴出cglib的测试代码,测试代码改自论坛中另外一个介绍cglib使用的帖子。

1)被代理类findInfo方法调用findInfo2方法

Java代码 复制代码
  1. package x.y.aop.cglib;   
  2.   
  3. import org.apache.commons.logging.Log;   
  4. import org.apache.commons.logging.LogFactory;   
  5.   
  6. public class StudentInfoServiceImpl {   
  7.   
  8.     protected final Log logger = LogFactory.getLog(getClass());   
  9.        
  10.     public void findInfo(String name){   
  11.         logger.info("你目前输入的名字是:"+name);   
  12.         //StudentInfoServiceImpl类内部调用!   
  13.         findInfo2();   
  14.         logger.info("complete method findInfo");   
  15.     }   
  16.        
  17.     public void findInfo2(){   
  18.         logger.info("i'm in findinfo2!!!");   
  19.     }   
  20.        
  21.        
  22. }  
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拦截类

Java代码 复制代码
  1. package x.y.aop.cglib;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. import net.sf.cglib.proxy.Enhancer;   
  6. import net.sf.cglib.proxy.MethodInterceptor;   
  7. import net.sf.cglib.proxy.MethodProxy;   
  8.   
  9. import org.apache.commons.logging.Log;   
  10. import org.apache.commons.logging.LogFactory;   
  11.   
  12. public class AOPInstrumenter implements MethodInterceptor {   
  13.   
  14.     protected final Log logger = LogFactory.getLog(getClass());   
  15.   
  16.     private Enhancer enhancer = new Enhancer();   
  17.   
  18.     public Object getInstrumentedClass(Class clz) {   
  19.         enhancer.setSuperclass(clz);   
  20.         enhancer.setCallback(this);   
  21.         return enhancer.create();   
  22.     }   
  23.   
  24.     public Object intercept(Object o, Method method, Object[] args,   
  25.             MethodProxy proxy) throws Throwable {   
  26.         logger.info("进入代理 方法:" + method.getName());   
  27.         logger.info("开始执行原始方法:" + method.getName());   
  28.         Object result = proxy.invokeSuper(o, args);   
  29.         logger.info("退出代理 方法:" + method.getName());   
  30.         return result;   
  31.     }   
  32.   
  33. }  
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方法

Java代码 复制代码
  1. package x.y.aop.cglib;   
  2.   
  3. public class main {   
  4.   
  5.     public static void main(String[] args) {   
  6.         AOPInstrumenter instrumenter = new AOPInstrumenter();   
  7.         StudentInfoServiceImpl studentInfo = (StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class);   
  8.         studentInfo.findInfo("阿飞");   
  9.     }   
  10. }  
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日志输入

Java代码 复制代码
  1. main - 进入代理 方法:findInfo   
  2. main - 开始执行原始方法:findInfo   
  3. main - 你目前输入的名字是:阿飞   
  4. main - 进入代理 方法:findInfo2   
  5. main - 开始执行原始方法:findInfo2   
  6. main - i'm in findinfo2!!!   
  7. main - 退出代理 方法:findInfo2   
  8. main - complete method findInfo   
  9. 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
分享到:
评论

相关推荐

    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 AOP 使用了两种代理机制来实现:基于 JDK 的动态代理和基于 CGLib 的动态代理。JDK 动态代理只支持接口的代理,而不支持类的代理。CGLib 采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用...

    深入理解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 的魅力

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

    2020面试题总结Spring篇.pdf

    事务传播行为是指在一个已存在的事务中调用另一个方法时,如何处理这两个方法间的事务关系。Spring提供了多种不同的事务传播行为选项,以便开发者能够更灵活地控制事务的范围。 #### 传播行为类型: 1. **...

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

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

    java事务 - 使用动态代理

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

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