Spring3开发实战 之 第三章:AOP开发(2)(三)

2014-11-24 08:36:49 · 作者: · 浏览: 6
命名(id或name)结尾的Bean
切入点表达式的基本示例,使用reference pointcut
引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持,如下所示:

java代码:
查看复制到剪贴板打印
@Pointcut(value="bean(*Service)") //命名切入点1
private void pointcut1(){}
@Pointcut(value="@args(cn.javass.spring.chapter6.Secure)") //命名切入点2
private void pointcut2(){}

@Before(value = "pointcut1() && pointcut2()") //引用命名切入点
public void referencePointcutTest1(JoinPoint jp) {
dump("pointcut1() && pointcut2()", jp);
}
声明通知
通知是跟一个切入点表达式关联起来的,并且在切入点匹配的方法执行之前或者之后或者之前和之后运行。 切入点表达式可能是指向已命名的切入点的简单引用或者是一个已经声明过的切入点表达式。
前置通知(Before advice) ,使用 @Before 注解声明

java代码:
查看复制到剪贴板打印
@Aspect
public class BeforeExample {
@Before("execution(* com.xyz.myapp.dao.*.*(..))")
public void doAccessCheck() {
// ...
}
}
返回后通知(After returning advice) ,使用 @AfterReturning注解声明
后通知(After (finally) advice) ,使用 @After注解声明
抛出后通知(After throwing advice) ,使用 @AfterThrowing注解声明
可以将抛出的异常绑定到通知的一个参数上 ,如下:

java代码:
查看复制到剪贴板打印
@AfterThrowing(
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",
throwing="ex")
public void doRecoveryActions(Exception ex) {
// ...
}
环绕通知(Around Advice) ,使用 @Around注解声明

java代码:
查看复制到剪贴板打印
@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
给Advice传递参数
通常情况下,Advice都需要获取一定的参数,比如:Before需要截获传入的参数,而After需要获取方法的返回值等等。下面介绍两种方式
方式一:使用JoinPoint来给Advice的方法传递参数
Spring AOP提供使用org.aspectj.lang.JoinPoint类型获取连接点数据,任何通知方法的第一个参数都可以是JoinPoint(环绕通知是ProceedingJoinPoint,JoinPoint子类),当然第一个参数位置也可以是JoinPoint.StaticPart类型,这个只返回连接点的静态部分。
1:JoinPoint:提供访问当前被通知方法的目标对象、代理对象、方法参数等数据

java代码:
查看复制到剪贴板打印
public interface JoinPoint {
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
Object getThis(); //返回AOP代理对象
Object getTarget(); //返回目标对象
Object[] getArgs(); //返回被通知方法参数列表
Signature getSignature(); //返回当前连接点签名
SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
String getKind(); //连接点类型
StaticPart getStaticPart(); //返回连接点静态部分
}
2:ProceedingJoinPoint:用于环绕通知,使用proceed()方法来执行目标方法

java代码:
查看复制到剪贴板打印
public interface ProceedingJoinPoint extends JoinPoint {
public Object proceed() throws Throwable;
public Object proceed(Object[] args) throws Throwable;
}
3:JoinPoint.StaticPart:提供访问连接点的静态部分,如被通知方法签名、连接点类型等

java代码:
查看复制到剪贴板打印
public interface StaticPart {
Signature getSignature(); //返回当前连接点签名
String getKind(); //连接点类型
int getId(); //唯一标识
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
}
4:示例:使用如下方式在通知方法上声明,必须是在第一个参数,然后使用jp.getArgs()就能获取到被通知方法参数:

java代码:
查看复制到剪贴板打印
@Before(value="execution(* sayBefore(*))")
public void before(JoinPoint jp) {}
@Before(value="execution(* sayBefore(*))")
public void before(JoinPoint.StaticPart jp) {}
方式二:使用args来给Advice的方法传递参数,示例如:

java代码:
查看复制到剪贴板打印
@Before(value="execution(* test(*)) && args(param)", argNames="param")
public void before1(String param) {
System.out.println("=