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(返回值 空格 方法选择)。两部分组成,中间一定要有空格。 方法选择:包名[类名].*()。设定要拦截的方法签名。
|
|