Spring-AOP 基于Schema配置切面
- 概述
- 简单切面配置实例
- 示例
- 配置命名切点
- 示例
- 各种增强类型的配置
- 示例
- 绑定连接点信息
- Advisor配置
概述
如果项目不能使用Java5.0, 那么就无法使用基于@AspectJ注解的切面。 但是Spring提供了基于Schema配置的方法,它完全可以替代基于@AspectJ注解声明切面的方式。
基于@AspectJ注解的切面,本质上是将切点、增强类型的信息使用注解描述,我们将这两个信息转移到Schema的xml配置文件中,只是形式变了,本质还是相同的。
使用基于Schema的切面定义后,切点、增强类型的注解信息从切面类中剥离出来,原来的切面类也就蜕变为真正意义上的POJO了
简单切面配置实例
代码已托管到Github—> https://github.com/yangshangwei/SpringMaster
示例
首先来配置一个基于Schema的切面,它使用aop命名空间。
<?xml version="1.0" encoding="UTF-8"?>
<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.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- (1)配置一个基于Schema的切面,它使用了aop命名空间, 因此首先声明aop及指定aop文件 如上--><!-- ref引用adviceMethods,紧接着声明切点表达式 以及增强方法使用adviceMethodsBean中的crossCutting方法-->
<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,也可以通过使用context命名空间扫描注解的方式实例化 -->
<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 -->
<bean id="adviceMethods" class="com.xgj.aop.spring.advisor.schema.demo.AdviceMethods"/></beans>
解析:
使用一个
<aop:aspect>
元素标签定义切面,其内部可以定义多个增强。在
<aop:config>
元素中可以定义多个切面。通过
<aop:before>
声明了一个前置增强,并通过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 {@Testpublic 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"><!-- (1) ---><aop:pointcut id="bussinessOneProgram" expression="target(com.xgj.aop.spring.advisor.schema.namePointcut.BussinessOne) and execution(* program(..))" /><aop:aspect ref="adviceMethods"><!-- (2) ---><aop:before pointcut-ref="bussinessOneProgram" method="crossCutting"/></aop:aspect>
</aop:config>
- 在(1)处使用
<aop:pointcut>
定义了一个切点,并通过id属性进行命名. - 在(2)通过pointcut-ref引用这个命名的切点。和
<aop:before>
一样,除了引介增强外,其他任意增强类型都拥有pointcut、pointcut-ref和method这3个属性。
当然了,
<aop:pointcut>
如果位于<aop:aspect>
元素中,则该命名切点只能被当前<aop:aspect>
内定义的元素访问到。 为了能让整个<aop:config>
元素中定义的所有增强访问,必须在<aop:config>
元素下定义切点,如上所示。如果有在
<aop:config>
元素下直接定义<aop:pointcut>
,则必须保证<aop:pointcut>
在<aop:aspect>
之前定义。 在<aop:config>
元素下还可以定义<aop:advisor>
,三者的顺序要求为:首先是<aop:pointcut>
,然后是<aop:advisor>
,最后是<aop:aspect>
- 在(2)通过pointcut-ref引用这个命名的切点。和
各种增强类型的配置
基于Schema定义的切面和基于@AspectJ定义的切面内容基本一致,只是在表现形式上存在差异罢了。
下面通过实例来演示
示例
业务类
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 cautiousif (bussinessName != null && "bug".equals(bussinessName))throw new IllegalArgumentException("iae Exception");elsethrow 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 {@Overridepublic 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 {@Overridepublic void fixBug() {System.out.println("IntfBussinessImpl fixBug executed");}}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://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"/><!-- final抛出命名切点 --><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"/><!-- final增强 --><aop:after pointcut-ref="after" method="afterMethod"/><!-- 引介增强 types-matching哪些类需要引介接口的实现 implement-interface要引介实现的接口 default-impl 引介默认的实现类--><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 {@Testpublic 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
重点说一下引介增强 : 通过<aop:declare-parent>
配置引介增强, 引介增强和其他类型的增强有所不同,它没有method、pointcut和point-ref属性
引介增强通过types-matching以及AspectJ切点表达式语法指定哪些bean需要引介接口的实现, implement-interface要引介实现的接口 , default-impl 引介默认的实现类
值的注意的是,虽然<aop:declare-parent>
么有method属性指定增强方法所在的Bean,但是<aop:aspect ref="adviceMethods">
中的ref属性依然要指定一个增强Bean。
绑定连接点信息
基于Schema配置的增强方法绑定连接点信息和基于@AspectJ绑定连接点信息所使用的方式没有区别。
1)所有增强类型对应的方法第一个入参都可以声明为JoinPoint(环绕增强可声明为ProceedingJoinPoint)访问连接点信息;
2)
<aop:after-returning>
(后置增强)可以通过returning属性绑定连接点方法的返回值,<aop:after-throwing>
(抛出异常增强)可以通过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()----");}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- (1)配置一个基于Schema的切面,它使用了aop命名空间, 因此首先声明aop及指定aop文件 如上--><!-- ref引用adviceMethods,紧接着引用命名切点 以及增强方法使用adviceMethodsBean中的crossCutting方法-->
<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><!-- 扫描类包以及使用注解定义的bean -->
<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 {@Testpublic 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
program:Spring, number:8
----bindJoinPointParams()----
name:Spring4
number:10
----bindJoinPointParams()----
BussinessBindParam fixBug executed
program:Spring4, number:10,salary20000.0
Advisor配置
Advisor是Spring中切面概念的对应物,是切点和增强的复合体,不过仅包含一个切点和一个增强。在AspectJ中没有对应的等价物,在aop Schema配置样式中,可以通过配置一个Advisor。通过advice-ref属性引用基于接口定义的增强,通过pointcut定义切点表达式,或者通过pointcut-ref引用一个命名的切点。
接口 及实现类
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 {@Overridepublic void greetTo(String name) {System.out.println("greetTo " + name + "\n");}@Overridepublic 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*/@Overridepublic void before(Method method, Object[] args, Object target)throws Throwable {String clientName = (String) args[0];System.out.println("How are you " + clientName + " ?");}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- (1)配置一个基于Schema的切面,它使用了aop命名空间, 因此首先声明aop及指定aop文件 如上--><!-- ref引用adviceMethods,紧接着引用命名切点 以及增强方法使用adviceMethodsBean中的crossCutting方法-->
<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><!-- 扫描类包以及使用注解定义的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.schema.advisor"/>
<!-- advice -->
<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 {@Testpublic 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 XiaoGongJiangserverTo XiaoGongJiang
Spring-AOP 基于Schema配置切面相关推荐
- Java框架篇---spring aop两种配置方式
Java框架篇---spring aop两种配置方式 第一种:注解配置AOP 注解配置AOP(使用 AspectJ 类库实现的),大致分为三步: 1. 使用注解@Aspect来定义一个切面,在切面中 ...
- java @around,Spring AOP基于注解的Around通知
是一种建议类型,可确保方法执行前后的通知可以运行. 以下是通知的语法: 语法 @Pointcut("execution(* com.yiibai.Student.getAge(..))&qu ...
- Spring AOP统一功能处理(切面、切点、连接点、通知)
目录 一. AOP的一些前置知识 1.1什么是Aop 1.2 AOP的作用 1.3AOP基础组成 二.SpringAOP的实现 2.1添加SpringAOP框架支持 2.2定义切面(Aspect) 2 ...
- 面向切面(AOP)之Spring接口方式 schema配置方式 aspectj注解方式
一.初识AOP 关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节 1.AOP:Aspect-O ...
- spring aop xml事务配置
<aop:config> <!-- 通过aop定义事务增强切面--><aop:pointcut id="serviceMethod" expressi ...
- 基于Schema配置的AOP
一.切面配置 1 <aop:config proxy-target-class="true"> 2 <aop:pointcut id="pointcut ...
- Spring AOP之注解配置篇
AOP注解使用必要配置 在进行 AOP 注解配置前我们需要先在我们的配置文件中加入如下配置: <context:component-scan base-package="cn.zhuo ...
- 从代理机制到Spring AOP
这篇文章准备从Java的代理机制讲到Spring的AOP. 1.代理模式 代理模式是很常见的一种设计模式,代理一词拆开来看就是代为受理,那显然是要涉及到请求被代理的委托方,提供代理的代理方,以及想要通 ...
- 从代理机制到Spring AOP,这篇给你安排的明明白白的
这篇文章准备从Java的代理机制讲到Spring的AOP. 1.代理模式 代理模式是很常见的一种设计模式,代理一词拆开来看就是代为受理,那显然是要涉及到请求被代理的委托方,提供代理的代理方,以及想要通 ...
最新文章
- MIT:机器学习预测2018世界杯冠军
- 一个API调用27个NLP预训练模型:BERT、GPT-2全囊括,像导入NumPy一样容易
- Android 侧滑多层view显示
- 【CodeForces - 520B】Two Buttons (bfs或dp或时光倒流,trick)
- Exchange 服务器可支持性矩阵
- 大数据在智慧城市中的应用有哪些
- wke升级vs2010,vs2013
- yaml 变量引用_yaml语法
- protect 继承_【private,public,protect三种继承方式的区别】
- 线性约束最优化问题的Frank-Wolfe方法
- RTX3060安装pytorch
- qPCR定量方法在肠道微生物特定种属定量应用
- 【HPU】[1732]序列的区间操作
- 电离释放型动态水处理器
- DNS服务详解(解析+搭建)
- web ui自动化之弹窗操作 - alert模块
- 微信群总有人发广告?用Python写一个自动化机器人消灭他
- dpdk 多进程共享内存描述信息的机制
- 今日头条(layout下xml布局)
- OpenCV-Python图像形态变换概述及morphologyEx函数介绍
热门文章
- sklearn.naive_bayes
- Leetcode 38.外观数列 (每日一题 20210702)
- 社交网络分析与反欺诈
- python 笔记 pickle json
- Python应用实战-在Python中进行数据处理操作的几种方法
- python递归深度报错--RuntimeError: maximum recursion depth exceeded
- Linux查看utmp文件,linuxc操作utmp和wtmp文件接口
- tf.ConfigProto()函数
- android开发--翻转闹铃(从制作到打包)
- 五分钟学会悲观乐观锁-java vs mysql vs redis三种实现