在配置Spring AOP时,可以使用
@H_404_3@org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator来完成目标服务的拦截。
比如:
会在helloService的方法执行之前,先执行helloServiceAOP。
HelloServiceImpl定义如下:
HelloServiceAOP定义如下:
@H_404_3@package com.bing.aoptest.aop; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class HelloServiceAOP implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("\nHelloServiceAOP: " + invocation.getMethod().getDeclaringClass().getName()); return invocation.proceed();//放行,调用目标方法 } }那么,如果定义了两个BeanNameAutoProxyCreator会怎么样呢?
xml配置如下:
helloServiceAOP和helloServiceInterceptor都拦截目标对象,但定义在不同的BeanNameAutoProxyCreator里面。
helloServiceAOP定义如下:
package com.bing.aoptest.aop;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class HelloServiceAOP implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("\nHelloServiceAOP: " + invocation.getMethod().getDeclaringClass().getName()); Method m = AOPUtil.getMethod(invocation); System.out.println("HelloServiceAOP,method对象:" + m); System.out.println("HelloServiceAOP,invocation对象:" + invocation); return invocation.proceed(); }
}
helloServiceInterceptor定义如下:
@H_404_3@package com.bing.aoptest.aop; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class HelloServiceInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("\nHelloServiceInterceptor: " + invocation.getMethod().getDeclaringClass().getName()); Method m = AOPUtil.getMethod(invocation); System.out.println("HelloServiceInterceptor,method对象:" + m); System.out.println("HelloServiceInterceptor,invocation对象:" + invocation); return invocation.proceed(); } } @H_404_3@package com.bing.aoptest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.bing.aoptest.service.HelloService; /** * Hello world! * */ public class App { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml"); HelloService hs = (HelloService) context.getBean("helloService"); hs.say(); } }输出结果:
@H_404_3@HelloServiceAOP: com.bing.aoptest.service.HelloService HelloServiceAOP,method对象:public final void com.sun.proxy.$Proxy0.say() HelloServiceAOP,invocation对象:ReflectiveMethodInvocation: public abstract void com.bing.aoptest.service.HelloService.say(); target is of class [com.sun.proxy.$Proxy0] HelloServiceInterceptor: com.bing.aoptest.service.HelloService HelloServiceInterceptor,method对象:public void com.bing.aoptest.service.HelloServiceImpl.say() HelloServiceInterceptor,invocation对象:ReflectiveMethodInvocation: public abstract void com.bing.aoptest.service.HelloService.say(); target is of class [com.bing.aoptest.service.HelloServiceImpl] Hello请注意:
HelloServiceAOP,method对象:public final void com.sun.proxy.$Proxy0.say()
HelloServiceInterceptor,method对象:public void com.bing.aoptest.service.HelloServiceImpl.say()
为什么method对象不都是public void com.bing.aoptest.service.HelloServiceImpl.say()呢?
原因
定义了两个org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator,按照顺序分别计作A,B,A会为目标对象T生成代理对象P1,B会为P1生成代理对象P2,代理逻辑就变成:
P2代理P1,P1代理T,而不是P2、P1都代理T。
所以,调用T的方法时,应该先执行P1,但P2代理了P1,最终先执行P2,再执行P1,在执行T。
这种情况下,如果T的方法上有注解,只有P1能够拿到注解信息,P2是拿不到的。
所以,不要定义个多个org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator的bean。