锁定老帖子 主题:请问Spring AOP 是否支持嵌套?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-12-24
package aop; public interface SomeService { void someMethod(); void someInnerMethod(); } package aop; import org.apache.log4j.Logger; import org.springframework.context.ApplicationContext; public class SomeServiceImpl implements SomeService { private static final Logger log = Logger.getLogger(SomeServiceImpl.class); protected static ApplicationContext ctx; public void someMethod() { someInnerMethod(); log.debug("someMethod"); } public void someInnerMethod() { log.debug("someInnerMethod"); } } package aop; package com.gxlu.srm; import junit.framework.TestCase; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SomeServiceTest extends TestCase { protected void setUp() throws Exception { String[] paths = { "classpath:applicationContext-aop.xml" }; ctx = new ClassPathXmlApplicationContext(paths); } public void testAop() { SomeService someService = (SomeService) ctx.getBean("someService"); someService.someMethod(); someService.someInnerMethod(); } } <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/> <bean id="someServiceTarget" class="aop.SomeServiceImpl"/> <bean id="someService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"><value>aop.SomeService</value></property> <property name="target"><ref local="someServiceTarget"/></property> <property name="interceptorNames"> <list> <value>someAdvisor</value> </list> </property> </bean> <bean id="someAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"><ref local="debugInterceptor"/></property> <property name="patterns"> <list> <value>aop\.SomeService\.someMethod</value> <value>aop\.SomeService\.someInnerMethod</value> </list> </property> </bean> </beans> log4j.logger.org.springframework.aop=DEBUG log4j.logger.aop=DEBUG 日志显示 [srm] 2006-12-24 23:06:16.953 < INFO> [main] org.springframework.aop.framework.DefaultAopProxyFactory.<clinit>(61) | CGLIB2 not available: proxyTargetClass feature disabled [srm] 2006-12-24 23:06:16.984 <DEBUG> [main] org.springframework.aop.framework.ProxyFactoryBean.addInterface(216) | Added new aspect interface: aop.SomeService [srm] 2006-12-24 23:06:17.015 <DEBUG> [main] org.springframework.aop.framework.ProxyFactoryBean.initializeAdvisorChain(420) | Configuring advisor or advice 'someAdvisor' [srm] 2006-12-24 23:06:17.015 <DEBUG> [main] org.springframework.aop.framework.ProxyFactoryBean.addAdvisorOnChainCreation(526) | Adding advisor or TargetSource [org.springframework.aop.support.RegexpMethodPointcutAdvisor: advice [org.springframework.aop.interceptor.DebugInterceptor@126804e], pointcut patterns {aop\.SomeService\.someMethod, aop\.SomeService\.someInnerMethod}] with name [someAdvisor] [srm] 2006-12-24 23:06:17.015 <DEBUG> [main] org.springframework.aop.framework.ProxyFactoryBean.addAdvisorOnChainCreation(535) | Adding advisor with name [someAdvisor] [srm] 2006-12-24 23:06:17.015 <DEBUG> [main] org.springframework.aop.framework.ProxyFactoryBean.freshTargetSource(549) | Not refreshing target: bean name not specified in interceptorNames [srm] 2006-12-24 23:06:17.015 <DEBUG> [main] org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(109) | Creating JDK dynamic proxy for [aop.SomeServiceImpl] [b][color=blue][srm] 2006-12-24 23:06:17.062 <DEBUG> [main] org.springframework.aop.interceptor.DebugInterceptor.invokeUnderTrace(57) | Entering invocation: method 'someMethod', arguments []; target is of class [aop.SomeServiceImpl]; count=1 [srm] 2006-12-24 23:06:17.062 <DEBUG> [main] aop.SomeServiceImpl.someInnerMethod(17) | someInnerMethod [srm] 2006-12-24 23:06:17.078 <DEBUG> [main] aop.SomeServiceImpl.someMethod(13) | someMethod [srm] 2006-12-24 23:06:17.078 <DEBUG> [main] org.springframework.aop.interceptor.DebugInterceptor.invokeUnderTrace(60) | Exiting invocation: method 'someMethod', arguments []; target is of class [aop.SomeServiceImpl]; count=1[/color][/b][b][color=red][srm] 2006-12-24 23:06:17.078 <DEBUG> [main] org.springframework.aop.interceptor.DebugInterceptor.invokeUnderTrace(57) | Entering invocation: method 'someInnerMethod', arguments []; target is of class [aop.SomeServiceImpl]; count=2 [srm] 2006-12-24 23:06:17.078 <DEBUG> [main] aop.SomeServiceImpl.someInnerMethod(17) | someInnerMethod [srm] 2006-12-24 23:06:17.078 <DEBUG> [main] org.springframework.aop.interceptor.DebugInterceptor.invokeUnderTrace(60) | Exiting invocation: method 'someInnerMethod', arguments []; target is of class [aop.SomeServiceImpl]; count=2[/color][/b] 单独进入'someInnerMethod'时 AOP起作用 但通过'someMethod'调用someInnerMethod时为什么没有出现Entering invocation: method 'someInnerMethod'的日志? 是否SpringAOP不支持嵌套?! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-12-25
spring aop 原理上是创建一个 proxy
通过'someMethod'调用someInnerMethod 时是普通的java 函数调用,并不会调用到proxy上,所以aop不起作用 使用aspectJ 的静态织入组件可能会起作用 |
|
返回顶楼 | |
发表时间:2006-12-25
pikachu 写道 spring aop 原理上是创建一个 proxy
通过'someMethod'调用someInnerMethod 时是普通的java 函数调用,并不会调用到proxy上,所以aop不起作用 使用aspectJ 的静态织入组件可能会起作用 同意,cglib是继承原来的类,jdk proxy是继承Proxy类,返回的是一个新的"包装"过的类,但原来Object方法中(super中)的调用还是属于super中的. |
|
返回顶楼 | |
发表时间:2007-04-28
如果去反编辑一下那些代理类,就什么都明白了,public final class ItestImpProxy extends Proxy
implements ITest { public ItestImpProxy(InvocationHandler invocationhandler) { super(invocationhandler); } public final void test1() { try { super.h.invoke(this, m3, null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)super.h.invoke(this, m2, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)super.h.invoke(this, m0, null)).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void test2() { try { super.h.invoke(this, m4, null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void test3() { try { super.h.invoke(this, m5, null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final boolean equals(Object obj) { try { return ((Boolean)super.h.invoke(this, m1, new Object[] { obj })).booleanValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } private static Method m3; private static Method m2; private static Method m0; private static Method m4; private static Method m5; private static Method m1; static { try { m3 = Class.forName("reflect.aop.ITest").getMethod("test1", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m4 = Class.forName("reflect.aop.ITest").getMethod("test2", new Class[0]); m5 = Class.forName("reflect.aop.ITest").getMethod("test3", new Class[0]); m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); } catch(NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexception.getMessage()); } catch(ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexception.getMessage()); } } } |
|
返回顶楼 | |
发表时间:2007-04-28
可以看出的,基于jdk proxy 是不可能实现嵌套的,cglib是基于子类,具体源码还没时间去看呢,不太清楚,期待有人回答
|
|
返回顶楼 | |
发表时间:2007-04-29
只要在被spring拦截的方法中再调用其他被代理的对象的方法就可以实现嵌套拦截,如果调用自己对象的方法(包括继承的),只是普通对象的方法调用(这时自己是被剥去了代理的壳的原始对象),是不能被拦截的。
|
|
返回顶楼 | |
发表时间:2007-04-29
someMethod()调用someInnerMethod()根本就不是走的proxy.
起作用才怪了. |
|
返回顶楼 | |
发表时间:2007-08-03
这个问题也捆饶了我很久
|
|
返回顶楼 | |
发表时间:2007-08-04
yeshucheng 写道 这个问题也捆饶了我很久
我觉得自己的嵌套调用不被aop拦截挺好啊,保证了在一个事务里面, 如果你要实现嵌套调用的拦截,那么里面的方法不能用this来调用,直接写someInnerMethod();实际就是执行了this.someInnerMethod();这个this是剥离了aop代理的真正的SomeServiceImpl对象,而外面执行的someService.someMethod()这个someService对象是aop代理对象,只有调用代理对象的方法才有机会执行代理动作, 那么怎么在方法里面来调用代理对象,自己想办法吧,可以从spring容器中取得该对象,或者把该对象作为参数传到方法里面,或者可以在SomeServiceImpl类里加一个属性来引用自己的代理对象,如名为self,在使用前先设置一下,someService.setSelf(someService);把代理对象的引用保存到对象里面,在嵌套调用时调用self的方法而不是this。 |
|
返回顶楼 | |
发表时间:2007-08-04
janh 写道 yeshucheng 写道 这个问题也捆饶了我很久
那么怎么在方法里面来调用代理对象,自己想办法吧,可以从spring容器中取得该对象,或者把该对象作为参数传到方法里面,或者可以在SomeServiceImpl类里加一个属性来引用自己的代理对象,如名为self,在使用前先设置一下,someService.setSelf(someService);把代理对象的引用保存到对象里面,在嵌套调用时调用self的方法而不是this。 不知道janh是否试过? 我用过这个法子,但是这样好像不工作。异常。什么异常,什么原因没查。 这个问题,应该是设计问题。抽取方法,另行安排。 |
|
返回顶楼 | |