首先,在 xml 配置文件中,加入 aop 的资源:
< beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xmlns:context= "http://www.springframework.org/schema/context"
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.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd" >
< aop:aspectj-autoproxy proxy-target-class = "true"/>
定义一个切片类:
package aop.test.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component ;
/**
* 切面
*/
@Aspect @Component
public class MyInterceptor {
@Pointcut( "execution (* output.test.impl..*(..))") //括号里规定了目标对象的范围,第一个*表示函数的返回类型不限,第二个*表示此包和子包下的所有函数均可。第一个连续两点表示包含子包,第二个连续两点表示函数的参数不限。
private void anyMethod() {} //声明一个切入点
@Before ("anyMethod() && args(name)" ) // 如果函数的参数个数不为1,则不会执行此前置通知。括号里的 name,要和底下函数中参数名一致才行,否则报错。
public void doAccessCheck(String name) {
System. out.println( "前置通知:" + name );
}
@AfterReturning(pointcut= "anyMethod()",returning= "result")
public void doAfterReturning(String result) {
System. out.println( "后置通知:" + result );
}
@After( "anyMethod()")
public void doAfter() {
System. out.println( "最终通知" );
}
@AfterThrowing(pointcut= "anyMethod()",throwing= "e")
public void doAfterThrowing(Exception e) {
System. out.println( "例外通知:" + e );
}
@Around( "anyMethod()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
//if(){//判断用户是否在权限
System. out.println( "进入方法" );
Object result = pjp.proceed();
System. out.println( "退出方法" );
//}
return result;
}
}
用 @Aspect 注解的类,表示里面定义了很多拦截器,对一些函数执行前、后等加入通知。然后用 @Component (或者在xml中声明) 加入到 Spring 容器中。
HelloBean.output() 函数:
public void output() {
System. out.println( "name="+ name);
}
测试此切片类:
public void test() {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml" );
Hello hb = (Hello) ctx.getBean( "helloBean");
hb.output();
}
输出:
前置通知:Gong
进入方法
name=Gong
最终通知
后置通知:null
退出方法
注意 退出方法 和 后置通知 的顺序。
语法细节:
@Pointcut 中
execution (
java.lang.String output.test.impl..*(
java.lang.String,..))
表示匹配返回类型为String的、且第一个参数为String类型(其余参数不作要求) 的函数。如果想要匹配返回类型不是void的,可以用
execution (
!void output.test.impl..*(java.lang.String,..))