Spring-AOP 基于Schema配置切面

  • 概述
  • 简单切面配置实例
    • 示例
  • 配置命名切点
    • 示例
  • 各种增强类型的配置
    • 示例
  • 绑定连接点信息
  • Advisor配置

概述

如果项目不能使用Java5.0, 那么就无法使用基于@AspectJ注解的切面。 但是Spring提供了基于Schema配置的方法,它完全可以替代基于@AspectJ注解声明切面的方式。

基于@AspectJ注解的切面,本质上是将切点、增强类型的信息使用注解描述,我们将这两个信息转移到Schema的xml配置文件中,只是形式变了,本质还是相同的。

使用基于Schema的切面定义后,切点、增强类型的注解信息从切面类中剥离出来,原来的切面类也就蜕变为真正意义上的POJO了


简单切面配置实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster


示例

Spring-AOP 基于Schema配置切面_第1张图片

首先来配置一个基于Schema的切面,它使用aop命名空间。


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">




<aop:config proxy-target-class="true">
    <aop:aspect ref="adviceMethods">
        <aop:before  pointcut="target(com.xgj.aop.spring.advisor.schema.demo.BussinessOne) and execution(* program(..))" 
            method="crossCutting"/>
    aop:aspect>
aop:config>


<bean id="bussinessOne" class="com.xgj.aop.spring.advisor.schema.demo.BussinessOne"/>
<bean id="bussinessTwo" class="com.xgj.aop.spring.advisor.schema.demo.BussinessTwo"/>

<bean id="adviceMethods" class="com.xgj.aop.spring.advisor.schema.demo.AdviceMethods"/>

beans>

解析:

  • 使用一个元素标签定义切面,其内部可以定义多个增强。

  • 元素中可以定义多个切面。

  • 通过声明了一个前置增强,并通过pointcut属性定义切点表达式,切点表达式的语法和@AspectJ中所用的语法完全相同,由于&&在XML中使用不便,所以一般用and操作符代替。

  • 通过method属性指定增强的方法,该方法应该是adviceMethods Bean中的方法。


AdviceMethods是增强方法所在的类,它是一个普通的java类,没有任何特殊的地方,如下

package com.xgj.aop.spring.advisor.schema.demo;

/**
 * 
 * 
 * @ClassName: AdviceMethods
 * 
 * @Description: 增强方法所在的Bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午4:38:25
 */

public class AdviceMethods {

    /**
     * 
     * 
     * @Title: crossCutting
     * 
     * @Description: 改方法通过配置被用作增强方法
     * 
     * 
     * @return: void
     */
    public void crossCutting() {
        System.out.println("crossCutting executed");
    }
}

业务类

package com.xgj.aop.spring.advisor.schema.demo;

/**
 * 
 * 
 * @ClassName: BussinessOne
 * 
 * @Description: 普通POJO
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午4:37:56
 */

public class BussinessOne {

    public void program() {
        System.out.println("BussinessOne program executed");
    }

    public void fixBug() {
        System.out.println("BussinessOne fixBug executed");
    }
}
package com.xgj.aop.spring.advisor.schema.demo;

/**
 * 
 * 
 * @ClassName: BussinessTwo
 * 
 * @Description: 普通POJO
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午4:38:10
 */

public class BussinessTwo {
    public void program() {
        System.out.println("BussinessOne program executed");
    }

    public void fixBug() {
        System.out.println("BussinessOne fixBug executed");
    }
}

测试类

package com.xgj.aop.spring.advisor.schema.demo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ConfigBySchemaTest {

    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/schema/demo/conf-bySchema.xml");

        BussinessOne bussinessOne = ctx.getBean("bussinessOne",
                BussinessOne.class);
        BussinessTwo bussinessTwo = ctx.getBean("bussinessTwo",
                BussinessTwo.class);

        // 根据配置文件中的切点表达式
        // target(com.xgj.aop.spring.advisor.schema.demo.BussinessOne)and
        // execution(* program(..)) ,只有
        // bussinessOne.program()符合条件
        bussinessOne.program();
        bussinessOne.fixBug();

        bussinessTwo.program();
        bussinessTwo.fixBug();

    }

}

运行结果

2017-09-15 22:01:42,550  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@61ee30d2: startup date [Fri Sep 15 22:01:42 BOT 2017]; root of context hierarchy
2017-09-15 22:01:42,704  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/schema/demo/conf-bySchema.xml]
crossCutting executed
BussinessOne program executed
BussinessOne fixBug executed
BussinessOne program executed
BussinessOne fixBug executed

可见,切面被正确的实施到目标Bean中。


配置命名切点

上面的例子中通过pointcut属性声明的切点时匿名切点,它不能被其他增强或其他切面引用。Spring提供了命名切点的配置方式。

示例

<aop:config proxy-target-class="true">
    
    <aop:pointcut id="bussinessOneProgram"   expression="target(com.xgj.aop.spring.advisor.schema.namePointcut.BussinessOne) and execution(* program(..))" />

    <aop:aspect ref="adviceMethods">
        
        <aop:before  pointcut-ref="bussinessOneProgram" method="crossCutting"/>
    aop:aspect>
aop:config>
  • 在(1)处使用定义了一个切点,并通过id属性进行命名.
    • 在(2)通过pointcut-ref引用这个命名的切点。和一样,除了引介增强外,其他任意增强类型都拥有pointcut、pointcut-ref和method这3个属性。

    当然了,如果位于元素中,则该命名切点只能被当前内定义的元素访问到。 为了能让整个元素中定义的所有增强访问,必须在元素下定义切点,如上所示。

    如果有在元素下直接定义,则必须保证 之前定义。 在 元素下还可以定义 ,三者的顺序要求为:首先是,然后是 ,最后是


各种增强类型的配置

基于Schema定义的切面和基于@AspectJ定义的切面内容基本一致,只是在表现形式上存在差异罢了。

下面通过实例来演示

示例

Spring-AOP 基于Schema配置切面_第2张图片

业务类

package com.xgj.aop.spring.advisor.schema.advices;

public class BussinessSvc {

    public void dealBussinessBefore() {
        System.out.println("dealBussinessBefore executed");
    }

    public int dealWorkNumberForAfterReturring() {
        System.out.println("dealWorkNumberForAfterReturring executed");
        return 10;
    }

    public void dealWorkForAround(String workName) {
        System.out.println("dealWorkForAround executed");
    }

    public void dealBussinessForAfterThorowing(String bussinessName) {
        System.out.println("dealBussinessForAfterThorowing executed");
        // just a demo code ,in fact it's not cautious
        if (bussinessName != null && "bug".equals(bussinessName))
            throw new IllegalArgumentException("iae Exception");
        else
            throw new RuntimeException("re Exception");
    }

    public void dealWorkForAfter() {
        System.out.println("dealWorkForAfter executed");
    }
}

切面增强逻辑

package com.xgj.aop.spring.advisor.schema.advices;

import org.aspectj.lang.ProceedingJoinPoint;

public class AdviceMethods {
    /**
     * 
     * 
     * @Title: before
     * 
     * @Description: 前置增强对应的方法
     * 
     * @param name
     * 
     * @return: void
     */
    public void beforeMethod() {
        System.out.println("--Before CrossCuttingCode--");
    }

    /**
     * 
     * 
     * @Title: afterReturning
     * 
     * @Description: 后置增强对应方法 ,配置文件中的returing属性必须和增强方法的入参名称一致
     * 
     * @param retVal
     * 
     * @return: void
     */
    public void afterReturningMethod(int retVal) {
        System.out.println("----afterReturning() begin----");
        System.out.println("returnValue:" + retVal);
        System.out.println("----afterReturning() end----");
    }

    /**
     * 
     * 
     * @Title: aroundMethod
     * 
     * @Description: 环绕增强对应方法
     * 
     * @param pjp
     * 
     * @return: void
     * @throws Throwable
     */
    public void aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("----aroundMethod() begin----");
        System.out.println("args[0]:" + pjp.getArgs()[0]);
        // 执行目标类的目标方法
        pjp.proceed();
        System.out.println("----aroundMethod() end----");
    }

    /**
     * 
     * 
     * @Title: afterThrowingMethod
     * 
     * @Description: 抛出异常增强
     * 
     * @param iae
     * 
     * @return: void
     */
    public void afterThrowingMethod(IllegalArgumentException iae) {
        System.out.println("----afterThrowingMethod()----");
        System.out.println("exception msg:" + iae.getMessage());
        System.out.println("----afterThrowingMethod()----");
    }

    /**
     * 
     * 
     * @Title: afterMethod
     * 
     * @Description: final增强
     * 
     * 
     * @return: void
     */
    public void afterMethod() {
        System.out.println("----afterMethod()----");
    }
}

为了演示引介增强引入的几个接口和实现类

package com.xgj.aop.spring.advisor.schema.advices;

/**
 * 
 * 
 * @ClassName: InterfaceOne
 * 
 * @Description: 演示引介增强用
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午8:14:18
 */
public interface InterfaceOne {
    void dealAnotherWork();
}
package com.xgj.aop.spring.advisor.schema.advices;

/**
 * 
 * 
 * @ClassName: InterfaceOneImpl
 * 
 * @Description: 演示引介增强用
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午8:14:33
 */
public class InterfaceOneImpl implements InterfaceOne {

    @Override
    public void dealAnotherWork() {
        System.out.println("InterfaceOneImpl dealAnotherWork executed ");

    }

}
package com.xgj.aop.spring.advisor.schema.advices;

/**
 * 
 * 
 * @ClassName: IntfBussiness
 * 
 * @Description: 演示引介增强用
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午8:14:41
 */
public interface IntfBussiness {
    void fixBug();
}
package com.xgj.aop.spring.advisor.schema.advices;

/**
 * 
 * 
 * @ClassName: IntfBussinessImpl
 * 
 * @Description: 演示引介增强用
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午8:14:49
 */
public class IntfBussinessImpl implements IntfBussiness {

    @Override
    public void fixBug() {
        System.out.println("IntfBussinessImpl  fixBug executed");
    }

}

配置文件


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">

    <aop:config proxy-target-class="true">
        
        <aop:pointcut expression="execution(* dealBussinessBefore(..))" id="before" />
        
        <aop:pointcut expression="execution(* dealWorkNumberForAfterReturring(..))" id="afterReturnning" />
        
        <aop:pointcut expression="execution(* dealWorkForAround(..)) and within(com.xgj.aop.spring.advisor.schema.advices.BussinessSvc)" id="around" />
        
        <aop:pointcut expression="within(com.xgj.aop.spring.advisor.schema.advices.BussinessSvc) and execution(* dealBussinessForAfterThorowing(..))"  id="afterThrowing"/>
        
        <aop:pointcut expression="execution(* dealWorkForAfter(..))" id="after"/>
        

        <aop:aspect ref="adviceMethods">
            
            <aop:before pointcut-ref="before" method="beforeMethod" />
            
            <aop:after-returning pointcut-ref="afterReturnning"
                method="afterReturningMethod" returning="retVal" />
            
            <aop:around pointcut-ref="around" method="aroundMethod"/>
            
            <aop:after-throwing pointcut-ref="afterThrowing" method="afterThrowingMethod"  throwing="iae"/>
            
            <aop:after pointcut-ref="after" method="afterMethod"/>

            
            <aop:declare-parents 
                types-matching="com.xgj.aop.spring.advisor.schema.advices.IntfBussiness+" 
                implement-interface="com.xgj.aop.spring.advisor.schema.advices.InterfaceOne"
                default-impl="com.xgj.aop.spring.advisor.schema.advices.InterfaceOneImpl"/>
        aop:aspect>
    aop:config>
    
    <bean id="bussinessSvc" class="com.xgj.aop.spring.advisor.schema.advices.BussinessSvc" />
    <bean id="intfBussinessImpl" class="com.xgj.aop.spring.advisor.schema.advices.IntfBussinessImpl">bean>
    
    <bean id="adviceMethods" class="com.xgj.aop.spring.advisor.schema.advices.AdviceMethods" />
beans>

测试类

package com.xgj.aop.spring.advisor.schema.advices;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DifferentAdviceTest {

    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/schema/advices/conf-advices.xml");

        BussinessSvc bussinessSvc = ctx.getBean("bussinessSvc",
                BussinessSvc.class);
        // 方法执行前织入前置增强
        bussinessSvc.dealBussinessBefore();

        // 方法执行后织入后置增强
        bussinessSvc.dealWorkNumberForAfterReturring();

        // 方法执行时织入环绕增强
        bussinessSvc.dealWorkForAround("fixBug");

        // 方法执行时出现特定异常时织入异常抛出增强
        bussinessSvc.dealWorkForAfter();

        // 方法执行后,不管异常与否都执行的增强
        bussinessSvc.dealWorkForAfter();

        // 引介 --强制类型转换成功,说明也实现了另外的接口
        IntfBussinessImpl intfBussinessImpl = ctx.getBean("intfBussinessImpl",
                IntfBussinessImpl.class);
        ((InterfaceOne) intfBussinessImpl).dealAnotherWork();
    }
}

运行结果

2017-09-15 22:37:49,383  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@c24cb3: startup date [Fri Sep 15 22:37:49 BOT 2017]; root of context hierarchy
2017-09-15 22:37:49,485  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/schema/advices/conf-advices.xml]
--Before CrossCuttingCode--
dealBussinessBefore executed
dealWorkNumberForAfterReturring executed
----afterReturning() begin----
returnValue:10
----afterReturning() end----
----aroundMethod() begin----
args[0]:fixBug
dealWorkForAround executed
----aroundMethod() end----
dealWorkForAfter executed
----afterMethod()----
dealWorkForAfter executed
----afterMethod()----
InterfaceOneImpl dealAnotherWork executed 

重点说一下引介增强 : 通过配置引介增强, 引介增强和其他类型的增强有所不同,它没有method、pointcut和point-ref属性

引介增强通过types-matching以及AspectJ切点表达式语法指定哪些bean需要引介接口的实现, implement-interface要引介实现的接口 , default-impl 引介默认的实现类

值的注意的是,虽然么有method属性指定增强方法所在的Bean,但是中的ref属性依然要指定一个增强Bean。


绑定连接点信息

基于Schema配置的增强方法绑定连接点信息和基于@AspectJ绑定连接点信息所使用的方式没有区别。

  • 1)所有增强类型对应的方法第一个入参都可以声明为JoinPoint(环绕增强可声明为ProceedingJoinPoint)访问连接点信息;

  • 2)(后置增强)可以通过returning属性绑定连接点方法的返回值,(抛出异常增强)可以通过throwing属性绑定连接点方法所抛出的异常;

  • 3)所有增强类型都可以通过可绑定参数的切点函数绑定连接点方法的入参。

前两种已经阐述过了,下面我们来看第三种绑定参数的方法

这里写图片描述

业务类

package com.xgj.aop.spring.advisor.schema.bindParameter;

import org.springframework.stereotype.Component;

/**
 * 
 * 
 * @ClassName: BussinessBindParam
 * 
 * @Description: 使用注解定义的Bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午8:25:23
 */

@Component
public class BussinessBindParam {

    public void program(String name, int number) {
        System.out.println("BussinessBindParam program execute");
        System.out.println("program:" + name + ", number:" + number);
    }

    public void fixbug(String name, int number, double salary) {
        System.out.println("BussinessBindParam fixBug executed");
        System.out.println("program:" + name + ", number:" + number + ",salary"
                + salary);
    }
}

增强切面

package com.xgj.aop.spring.advisor.schema.bindParameter;

import org.springframework.stereotype.Component;

/**
 * 
 * 
 * @ClassName: AdviceMethodsBindParam
 * 
 * @Description: 使用注解定义的Bean,同时也是切面类
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午8:25:13
 */

@Component
public class AdviceMethodsBindParam {

    /**
     * 
     * 
     * @Title: crossCutting
     * 
     * @Description: 改方法通过配置被用作增强方法
     * 
     * 
     * @return: void
     */
    public void crossCutting(String name, int num) {
        System.out.println("----bindJoinPointParams()----");
        System.out.println("name:" + name);
        System.out.println("number:" + num);
        System.out.println("----bindJoinPointParams()----");
    }
}

配置文件


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">




<aop:config proxy-target-class="true">
    
    <aop:pointcut id="bussinessBindParamProgram" expression="target(com.xgj.aop.spring.advisor.schema.bindParameter.BussinessBindParam) and args(name,num,..)" />

    <aop:aspect ref="adviceMethodsBindParam">
        <aop:before  pointcut-ref="bussinessBindParamProgram" method="crossCutting"/>
    aop:aspect>
aop:config>


<context:component-scan base-package="com.xgj.aop.spring.advisor.schema.bindParameter"/>
beans>

切点表达式通过 args(name,num,..) 绑定了连接点的两个参数,对应增强类中的入参crossCutting(String name, int num) . 这两个地方声明的参数名必须相同

测试类

package com.xgj.aop.spring.advisor.schema.bindParameter;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AdviceMethodsBindParamTest {
    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/schema/bindParameter/conf-bindParam.xml");

        BussinessBindParam bussinessBindParam = ctx.getBean(
                "bussinessBindParam", BussinessBindParam.class);
        // args(name,num,..) 因此会匹配到
        bussinessBindParam.program("Spring", 8);

        // args(name,num,..) 因此会匹配到
        bussinessBindParam.fixbug("Spring4", 10, 20000);
    }
}

运行结果

2017-09-15 22:47:49,244  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6ac604: startup date [Fri Sep 15 22:47:49 BOT 2017]; root of context hierarchy
2017-09-15 22:47:49,350  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/schema/bindParameter/conf-bindParam.xml]
----bindJoinPointParams()----
name:Spring
number:8
----bindJoinPointParams()----
BussinessBindParam program execute
programSpring, number:8
----bindJoinPointParams()----
name:Spring4
number:10
----bindJoinPointParams()----
BussinessBindParam fixBug executed
programSpring4, number:10,salary20000.0

Advisor配置

Advisor是Spring中切面概念的对应物,是切点和增强的复合体,不过仅包含一个切点和一个增强。在AspectJ中没有对应的等价物,在aop Schema配置样式中,可以通过配置一个Advisor。通过advice-ref属性引用基于接口定义的增强,通过pointcut定义切点表达式,或者通过pointcut-ref引用一个命名的切点。

Spring-AOP 基于Schema配置切面_第3张图片

接口 及实现类

package com.xgj.aop.spring.advisor.schema.advisor;

public interface Waiter {

    void greetTo(String name);

    void serverTo(String name);
}
package com.xgj.aop.spring.advisor.schema.advisor;

import org.springframework.stereotype.Component;

@Component
public class NaiveWaiter implements Waiter {

    @Override
    public void greetTo(String name) {
        System.out.println("greetTo " + name + "\n");
    }

    @Override
    public void serverTo(String name) {
        System.out.println("serverTo " + name);
    }

}

前置增强

package com.xgj.aop.spring.advisor.schema.advisor;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
 * 
 * 
 * @ClassName: GreetingBeforeAdvice
 * 
 * @Description: 前置增强
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月13日 下午8:55:12
 */

public class GreetingBeforeAdvice implements MethodBeforeAdvice {

    /**
     * 前置增强方法 当该方法发生异常时,将阻止目标方法的执行
     * 
     * @param method
     *            目标类方法
     * @param objects
     *            目标类方法入参
     * @param target
     *            目标类对象实例
     * @throws Throwable
     */
    @Override
    public void before(Method method, Object[] args, Object target)
            throws Throwable {
        String clientName = (String) args[0];
        System.out.println("How are you " + clientName + " ?");
    }
}

配置文件


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">




<aop:config proxy-target-class="true">
    
    <aop:pointcut expression="execution(* com..*.Waiter.greetTo(..))" id="beforeAdvice"/>

    <aop:advisor advice-ref="greetingBeforeAdvice" pointcut-ref="beforeAdvice"/>

aop:config>


<context:component-scan base-package="com.xgj.aop.spring.advisor.schema.advisor"/>

<bean id="greetingBeforeAdvice" class="com.xgj.aop.spring.advisor.schema.advisor.GreetingBeforeAdvice"/>
beans>

测试类

package com.xgj.aop.spring.advisor.schema.advisor;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AdvisorTest {
    @Test
    public void test() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/schema/advisor/conf-advisor.xml");

        NaiveWaiter naiveWaiter = ctx.getBean("naiveWaiter", NaiveWaiter.class);
        naiveWaiter.greetTo("XiaoGongJiang");
        naiveWaiter.serverTo("XiaoGongJiang");

    }
}

运行结果

2017-09-15 23:47:57,497  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@61ee30d2: startup date [Fri Sep 15 23:47:57 BOT 2017]; root of context hierarchy
2017-09-15 23:47:57,599  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/schema/advisor/conf-advisor.xml]
How are you XiaoGongJiang ?
greetTo XiaoGongJiang

serverTo XiaoGongJiang

你可能感兴趣的:(【Spring-AOP】)