Spring2.X以后,有许多东西得到了改进,对AOP的实现和设置也提供了新增了两种方式:一种是基于XML Schema的设置;另一种是基于Annotation的支持。下面仅介绍注解的方式:
@Aspect
public class AdviceInterceptor {
@Pointcut("execution (* com.bhsc.AOP.target.*.*(..))")
// 声明一个切入点(第一个*后要留一个空格)
private void anyMethod() {
}
@Before("anyMethod()")// 前置通知
public void before() {
System.out.println("前置通知");
}
@AfterReturning("anyMethod()")//后置通知
public void afterReturning(){
System.out.println("后置通知");
}
}
@Aspect表明这是一个切面,包括了通知和切入点,Pointcut注解用来声明一个切入点,括号中的参数是切入点的表达式,这里的表达式的意思是对com.bhsc.AOP.target包下的所有方法进行拦截。关于切入点表达式后面会有详细的说明。anyMethod是为切入点起一个名字,后面的“通知”都要依赖这个名字。
<!-- 开启切面编程功能,搜索所有带有@Aspect注解的类,解析这个切面里的通知和切入点的定义 -->
<aop:aspectj-autoproxy />
<bean id="targetImple" class="com.bhsc.AOP.target.TargetImple" />
<bean id="theInterceptor"
class="com.bhsc.aop2.AdviceInterceptor" />
ApplicationContext ctx = new
ClassPathXmlApplicationContext("aop2.xml");
TargetInterface ti=(TargetInterface)
ctx.getBean("targetImple");
ti.hello("lisi");
ti.nihao("lisi");
前置通知
hello :lisi
后置通知
前置通知
你好 :lisi
后置通知
Pointcut表达式可以和Pointcut签名一起定义,这样,签名就可以给多个通知使用,比如前面的anyMethod,后面的通知都用到了它,@Before("anyMethod()"),这里如果有多个签名还可以使用&&,||等对签名进行操作。另外,也可以在通知上直接定义Pointcut表达式,还可以带上JoinPoint参数,主要的目的是取得一些与JointPoint相关的信息,比如:
@Before("execution (* com.bhsc.AOP.target.*.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("前置通知");
System.out.println("目标对象:"+joinPoint.getTarget());
System.out.println("参数:"+joinPoint.getArgs().toString());
System.out.println("签名信息::"+joinPoint.getSignature());
}
目标对象:com.bhsc.AOP.target.TargetImple@176cad3
参数:[Ljava.lang.Object;@1fe1feb
签名信息:
org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$MethodSignatureImpl@a084f8
其他通知
@After("anyMethod()")// 最终通知
public void after() {
System.out.println("最终通知");
}
@AfterThrowing("anyMethod()") // 例外通知
public void AfterThrowing() {
System.out.println("例外通知");
}
@Around("anyMethod()") //环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("进入环绕");
//if(){ // 进行一些判断,再执行环绕
Object result = pjp.proceed();
//}
System.out.println("退出环绕");
return result;
}
匹配参数和返回值
1.参数
@Before("anyMethod() && args(in)")// 前置通知
public void before(int in) {
System.out.println("前置通知");
System.out.println(in);
}
在前置通知的方法中有一个参数,然后再把此参数作为拦截条件(即是说拦截带有一个String类型参数的方法)。args的名字和before方法参数名字相同
2.返回值,AfterReturn在有返回值的时候执行
@AfterReturning(pointcut ="anyMethod()",returning = "in")//后置通知
public void afterReturning(JoinPoint joinPoint,int in){
// System.out.println("目标对象:"+joinPoint.getTarget());
// System.out.println("参数:"+joinPoint.getArgs().toString());
// System.out.println("签名信息::"+joinPoint.getSignature());
//
System.out.println("后置通知返回结果:"+in);
}
表达式切入点
1.格式:execution(返回值 空格 方法选择)。两部分组成,中间一定要有空格。
返回值:可以是*,说明拦截任何方法。Java.lang.String(全名),拦截返回值为String类型的方法。 常用的实例如下:
方法选择:包名[类名].*()。设定要拦截的方法签名。
表达式(省略execution) | 说明 |
(java.lang.String 方法选择略) | 拦截返回值为String类型的方法 |
(!void 方法选择略) | 拦截返回值非空的方法 |
(* com.asm..*.*(..)) | 拦截com.asm包及子包下每个类的全部方法 |
(* com.asm.*.*(..)) | 拦截com.asm包下每个类的全部方法 |
(* com.asm.User.*(..)) | 拦截asm包下User类的所有方法 |
(* com.asm.User.* | 拦截User类中第一个参数为String,后面参数任一的方法 |
| |
| |
联系客服