转自:http://www.iteye.com/topic/40553
单独使用service某方法aop有作用,但是在service中调用自己service的方法aop不起作用,解决:在自己的service中aop自己的实现
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]
spring aop 原理上是创建一个 proxy
通过'someMethod'调用someInnerMethod 时是普通的java 函数调用,并不会调用到proxy上,所以aop不起作用
使用aspectJ 的静态织入组件可能会起作用
cglib是继承原来的类,jdk proxy是继承Proxy类,返回的是一个新的"包装"过的类,但原来Object方法中(super中)的调用还是属于super中的.
只要在被spring拦截的方法中再调用其他被代理的对象的方法就可以实现嵌套拦截,如果调用自己对象的方法(包括继承的),只是普通对象的方法调用(这时自己是被剥去了代理的壳的原始对象),是不能被拦截的。
我觉得自己的嵌套调用不被aop拦截挺好啊,保证了在一个事务里面,
如果你要实现嵌套调用的拦截,那么里面的方法不能用this来调用,直接写someInnerMethod();实际就是执行了this.someInnerMethod();这个this是剥离了aop代理的真正的SomeServiceImpl对象,而外面执行的someService.someMethod()这个someService对象是aop代理对象,只有调用代理对象的方法才有机会执行代理动作,
那么怎么在方法里面来调用代理对象,自己想办法吧,可以从spring容器中取得该对象,或者把该对象作为参数传到方法里面,或者可以在SomeServiceImpl类里加一个属性来引用自己的代理对象,如名为self,在使用前先设置一下,someService.setSelf(someService);把代理对象的引用保存到对象里面,在嵌套调用时调用self的方法而不是this。