AOP的XML配置:配置了两个BeanNameAutoProxyCreator,会怎么样?

来源:互联网 发布:苹果7支持的网络制式 编辑:程序博客网 时间:2024/06/02 11:07

在配置Spring AOP时,可以使用

org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator

来完成目标服务的拦截。
比如:

<bean id="serviceInteceptorProxyCreator"        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">        <property name="interceptorNames">            <list>                <value>helloServiceAOP</value>            </list>        </property>        <property name="beanNames">            <value>                helloService            </value>        </property>    </bean>    <bean id="helloServiceAOP" class="com.bing.aoptest.aop.HelloServiceAOP" />    <bean id="helloService" class="com.bing.aoptest.service.HelloServiceImpl"></bean>

会在helloService的方法执行之前,先执行helloServiceAOP。
HelloServiceImpl定义如下:

package com.bing.aoptest.service;public class HelloServiceImpl implements HelloService {    public void say() {        System.out.println("Hello");    }}

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());        return invocation.proceed();//放行,调用目标方法    }}

那么,如果定义了两个BeanNameAutoProxyCreator会怎么样呢?
xml配置如下:

<?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="helloService" class="com.bing.aoptest.service.HelloServiceImpl"></bean>    <bean id="serviceInteceptorProxyCreator2"        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">        <property name="interceptorNames">            <list>                <value>helloServiceInterceptor</value>            </list>        </property>        <property name="beanNames">            <value>                helloService            </value>        </property>    </bean>    <bean id="serviceInteceptorProxyCreator"        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">        <property name="interceptorNames">            <list>                <value>helloServiceAOP</value>            </list>        </property>        <property name="beanNames">            <value>                helloService            </value>        </property>    </bean>    <bean id="helloServiceAOP" class="com.bing.aoptest.aop.HelloServiceAOP" />    <bean id="helloServiceInterceptor" class="com.bing.aoptest.aop.HelloServiceInterceptor" /></beans>

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定义如下:

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();    }}

调用方法:

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();    }}

输出结果:

HelloServiceAOP: com.bing.aoptest.service.HelloServiceHelloServiceAOP, 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.HelloServiceHelloServiceInterceptor, 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。

0 0
原创粉丝点击