Spring提供的AOP(Aspect-oriented Program)面向切面编程,是Spring的非常强大的功能。他能提供对方法的拦
截,然后在执行方法之前或者执行方法之后,甚至对执行方法的返回值异常等等情况执行相对应的代码,使得类似日
志,安全,权限拦截等功能都与逻辑代码分离,使代码专注于自己的任务。
下面我们来演示一个小例子,来说明一下使用Spring来进行AOP编程的过程。
首先写一个测试类
package com.bird.springidol;
public class Audience {
public void takeSeats(){
System.out.println("The audience is taking their seats");
}
public void turnOffCellPhones(){
System.out.println("The audience is turning off their cellphone");
}
public void applaud(){
System.out.println("clap clap clasp");
}
public void demandRefund(){
System.out.println("Boo! We want our money back!");
}
}
这个类将是一会演示AOP的演示效果的类。
然后就是需要拦截的方法,这里同样,我们写一个类
package com.bird.springidol;
public class Perform {
public void perform(){
System.out.println("Now Let's Perform");
}
}
然后分别将他们配置到Spring容器中进行管理
<bean id="audience" class="com.bird.springidol.Audience"/>
<bean id="perform" class="com.bird.springidol.Perform"/>
下面就是在XML中声明aspect了。首先需要在XML头引入AOP约定
<?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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
然后开启aspectj
<aop:aspectj-autoproxy/>
下面就可以进行配置了。
<aop:config>
<aop:aspect ref="audience">
<aop:before pointcut="execution(* com.bird.springidol.Perform.perform(..))"
method="takeSeats"/>
</aop:aspect>
</aop:config>
首先来解释一下
execution(* com.bird.springidol.Perform.perform(..))
这个是apsectj的表达式,其中*代表不关心这个方法的返回值,里面的就是需要拦截的方法的完整名称,括号里面的..代表不关心
这个方法的参数。
这样就会在运行perform的方法的时候,提前运行takeSeat这个方法。
如果对一个方法进行多次拦截,这样写就会变的很麻烦,我们来演示一下一种简单的配置方法
<aop:config>
<aop:aspect ref="audience">
<aop:pointcut expression="execution(* com.bird.springidol.Perform.perform(..))"
id="performance"/>
<aop:before method="takeSeats" pointcut-ref="performance"/>
<aop:before method="turnOffCellPhones" pointcut-ref="performance"/>
<aop:after-returning method="applaud" pointcut-ref="performance"/>
<aop:after-throwing method="demandRefund" pointcut-ref="performance"/>
</aop:aspect>
</aop:config>
这样给aop的切点表示了一个运行表达式并且给予了唯一的id,然后下面的切点就可以直接引用这个id来进行切面编程了。
这种方法在进行大范围拦截的时候很有用