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

在配置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.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。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 05:05:27

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

[刘阳Java]_Spring AOP基于XML配置介绍_第9讲

基于注解配置的Spring AOP固然简单,但是这节我们会给大家介绍基于XML配置的AOP是如何应用的.为什么这么说了,因为后面我们还会介绍到Spring对Dao操作的事务管理(基于AOP的XML文件方式来配置事务) 1. 基于XML文件方式来配置Spring的AOP,则我们需要的一些基本元素如下 <aop:config.../>,此标签很重要.它是在XML里配置AOP功能的核心标签 all aspect and advisor elements must be placed within a

spring相关—AOP编程—数学计算器情景示例讲解(包含注解配置AOP与XML配置AOP)

1.数学计算器 ①数学计算器接口[MathCalculator]            public void add(int i,int j);     public int sub(int i,int j);     public int multi(int i,int j);     public void divide(int i,int j);    ②提供简单实现:加减乘除运算[EasyImpl]    ③在简单实现的基础上让每一个计算方法都能够打印日志[LoginImpl]    

struts2中两种validation.xml的配置方式_百度文库

在struts中,根据配置的validation.xml文件进行页面输入项目的验证已经众所周知,本文介绍在struts2中两种validation.xml的配置方式.可以根据不同的需要进行不同的配置. 以下以login页面输入firstname,lastname,和age为例进行说明.struts.xml中,成功的话转向成功页面.不成功的话转回到原页面. 首先建立userbean文件.文件名:UserBean.java包:struts2.login.bean文件内容:package struts

Spring AOP基于xml配置实例

目录层级: AOP相关的几个类就是com.aop.xmltype这个报下的4个类. ICalculatorxml.java package com.aop.xmltype; /** * 加减乘除接口,用于AOP测试 * * @author Wei * */ public interface ICalculatorxml { /** * 加法 * * @param a * @param b * @return a+b */ public int doAdd(int a, int b); /** *

Spring_7_使用XML文件配置的方式实现AOP

接口类PersonService类与6相同. 1)实现类 PersonServiceBean: @Service // 使用自动扫描的方式自动装配 public class PersonServiceBean implements PersonService { @Override public void save(String name) { // throw new RuntimeException("异常"); System.out.println("调用save()方

spring aop的xml配置详解

在Spring配置文件中,所以AOP相关定义必须放在<aop:config>标签下,该标签下可以有<aop:pointcut>.<aop:advisor>.<aop:aspect>标签,配置顺序不可变. <aop:pointcut>:用来定义切入点,该切入点可以重用: <aop:advisor>:用来定义只有一个通知和一个切入点的切面: <aop:aspect>:用来定义切面,该切面可以包含多个切入点和通知,而且标签内部的

源码跟读,Spring是如何解析和加载xml中配置的beans

Spring版本基于: 跟踪代码源码基于: https://github.com/deng-cc/KeepLearning commit id:c009ce47bd19e1faf9e07f12086cd440b7799a63 1.配置启动Spring所需的监听器 web.xml中配置监听器 <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-cla

Spring框架笔记(二十八)—— 使用xml配置文件配置事务

就像前面AOP等部分介绍的,spring在实现AOP时提供了注解和xml配置两种方式.同样,配置事务管理,也可以使用xml文件配置. 这里我们将前面的例子重新复制一份,在tx2包中. 我们把注解全去掉,这里挑一个吧. package com.happBKs.spring.tx2; public interface BookShopDao { //根据书号获取书的单价 public int findBookPriceIsdn(String isbn); //更新书的库存,使得书号对应的库存-1 p

跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

Spring配置Bean有两种形式(XML和注解) 今天我们学习通过XML方式配置Bean 1. Bean的配置方式 通过全类名(反射)的方式   √ id:标识容器中的bean.id唯一. √ class:bean的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参的构造器 2.依赖注入的方式 1)属性注入:通过setter方法注入Bean的属性值或依赖的对象 属性注入使用<Property>元素,使用name指定Bean的属性名称,使用value指定Bean的属