Spring AOP 是否支持嵌套

来源:互联网 发布:mac apache php 403 编辑:程序博客网 时间:2024/05/22 10:51

转自: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=DEBUGlog4j.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。

0 0
原创粉丝点击