标签:spring 框架 aop aspectj annotation
6月14日,阴转雨。“四面垂杨十里荷,向云何处最花多, 画楼南畔夕阳和。天气乍凉人寂寞, 光阴须得酒消磨,且来花里听笙歌。”
面向切面的框架AspectJ邂逅Spring,不仅造就一种简洁,更带来更多的选择空间。
上篇的切面与代理配置方式,麻烦且繁琐。好在Spring 与 AspectJ 进行了集成,从接口和配置的泥潭爬出,善莫大焉。
下面把上一篇Spring的AOP 的例子改写一下,达到同样的效果。
1-3步骤不变。
4、定义一个 Aspect 切面类BallHandler.java
package edu.eurasia.aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class BallHandler {
static Logger logger = Logger.getLogger(TestBall.class);
@Pointcut("execution(* edu.eurasia.aop.WatchBallImpl.watchfoot*(..))")
public void watchfootball(){};
@Pointcut("execution(* edu.eurasia.aop.WatchBallImpl.watchbasket*(..))")
public void watchbasketball(){};
@Before(value="watchfootball()&& args(city,..)")
public void watchBefore(String city){
logger.debug(" 看球前,先去 " + city + " 咖啡馆喝杯巴西咖啡 ...");
}
@AfterReturning("watchbasketball() && args(city,..)")
public void watchAfter(String city){
logger.debug("看完球去 " + city + " 麦当劳吃汉堡包!");
}
}<span style="background-color: rgb(255, 255, 255);">
</span>
类上面标注的 @Aspect 注解,这表明该类是一个 Aspect(其实就是 Advisor)-切面类。该类无需实现任何的接口,只需定义一个方法(方法叫什么名字都无所谓)。
@Pointcut使用这个方法可以将edu.eurasia.aop.WatchBallImpl.watchfoot*(..)方法声明为poincut即切入点。作用,在watchfoot*(..)方法被调用的时候执行watchfootball()方法。其中execution是匹配方法执行的切入点,也就是spring最常用的切入点定义方式。
@Before(value="watchfootball()&& args(city,..)):@Before声明为在切入点方法执行之前执行,而后面没有直接声明切入点,而是value="watchfootball()",是因为如果@afterReturning等都有所改动的时候都必须全部改动,所以统一用Pointcut的watchfootball代替,这样子有改动的时候仅需改动一个地方。其它@AfterReturning类同。&&
args(city,..)可以获取切入点方法watchfoot*(..)的参数。
下面分析一下这个切点表达式:
execution(* edu.eurasia.aop.WatchBallImpl.watchfoot*(..))
execution():表示拦截方法,括号中可定义需要匹配的规则。
第一个“*”:表示方法的返回值是任意的。
第二个“*”:表示匹配该类中所有的方法。
(..):表示方法的参数是任意的。
5、编写spring的配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"
>
<!-- 定义Aspect -->
<bean id="ballHandler" class="edu.eurasia.aop.BallHandler" />
<!-- 定义Common -->
<bean id="watchBall" class="edu.eurasia.aop.WatchBallImpl" />
<!-- 启动AspectJ支持 -->
<aop:aspectj-autoproxy />
</beans> 6、编写测试类TestBall.javapackage edu.eurasia.aop;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestBall {
static Logger logger = Logger.getLogger(TestBall.class);
@Test
public void testball() {
logger.debug("test begin ");
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
WatchBall watchball = (WatchBall) ctx.getBean("watchBall");
watchball.watchfootball("里约热内卢");
logger.debug("----------------------------");
watchball.watchbasketball("德克萨斯州");
}
} 7、运行结果和环境配置
运行结果如下:
DEBUG [main] (BallHandler.java:21) - 看球前,先去 里约热内卢 咖啡馆喝杯巴西咖啡 ...DEBUG [main] (BallHandler.java:26) - 看完球去 德克萨斯州 麦当劳吃汉堡包!
本例使用spring 2.5.6,除了找出spring.jar,commons-logging-1.1.1.jar两个jar包,外加一个log4j.jar。还要下载aspectj-1.7.0.jar,解压后有四个JAR:aspectjrt.jar,aspectjtools.jar,aspectjweaver.jar和org.aspectj.matcher.jar。还需要下载一个aopalliance-1.0.jar。
目录结构如下:
8、基于配置的AspectJ
除了使用 @Aspect 注解来定义切面类以外,Spring AOP 也提供了基于配置的方式来定义切面类。
(1) 配置文件applicationContext.xml修改如下:
xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<!-- 定义Aspect -->
<bean id="ballHandler" class="edu.eurasia.aop.BallHandler" />
<!-- 定义Common -->
<bean id="watchBall" class="edu.eurasia.aop.WatchBallImpl" />
<aop:config>
<aop:aspect ref="ballHandler">
<aop:before method="watchBefore" arg-names="city"
pointcut="execution(* edu.eurasia.aop.WatchBallImpl.watchfoot*(String,..)) and args(city,..)" />
<aop:after method="watchAfter" arg-names="city"
pointcut="execution(* edu.eurasia.aop.WatchBallImpl.watchbasket*(String,..)) and args(city,..)" />
</aop:aspect>
</aop:config>
</beans>
(String,..)声明切入点至少含有一个String类型的参数,显然可以匹配WatchBallImpl中的watchfoot*(String city,..);args(n,..)声明给watchfoot*(String city,..)的第一个参数起了个别名“n”传递给Advice,如果<aop:before...>中arg-names不是“n”,将抛出异常。
(2) BallHandler.java 代码变化不大:
package edu.eurasia.aop;
import org.apache.log4j.Logger;
public class BallHandler {
static Logger logger = Logger.getLogger(TestBall.class);
public void watchBefore(String city){
logger.debug(" 看球前,先去 " + city + " 咖啡馆喝杯巴西咖啡 ...");
}
public void watchAfter(String city){
logger.debug("看完球去 " + city + " 麦当劳吃汉堡包!");
}
}
(3)其余代码和配置不变,运行结果相同。第二十九天 月出惊山鸟 —Spring的AOP_AspectJ @annotation,布布扣,bubuko.com
第二十九天 月出惊山鸟 —Spring的AOP_AspectJ @annotation
标签:spring 框架 aop aspectj annotation
原文地址:http://blog.csdn.net/zwszws/article/details/30989631