在之前只是进行了最为简单的AOP的拦截处理,只在操作之前与操作之后进行的拦截,但是在整个AOP处理里面有一个问题需要首先解决,那么就是参数问题
package cn.zwb.aop; import org.springframework.stereotype.Component; @Component public class ServiceAspect { public void serviceBefore(){ System.out.println("AO切面 执行日志记录操作"); } public void serviceBefore(Object arg){ System.out.println("AO切面 执行增加前的一个操作.参数="+arg); } public void serviceAfter(){ System.out.println("AOP切面 执行事务处理操作"); } }
此时对于serviceBefore(Object arg)这个方法上由于存在有参数的定义了,那么就必须修改切入点表达式
范例:定义切入点表达式
<aop:config proxy-target-class="true"> <!-- 首先定义程序的切入点 --> <aop:pointcut expression="execution(* cn.zwb..*.*(..)) and args(abc)" id="pointcut"/> <!-- 定义要使用的面向切面的处理类 --> <aop:aspect ref="serviceAspect"> <aop:before method="serviceBefore2" pointcut-ref="pointcut" arg-names="abc"/> <aop:after method="serviceAfter" pointcut="execution(* cn.zwb..*.*(..))"/> </aop:aspect> </aop:config>
除了在操作之前的拦截,也可以针对于操作的返回结果进行拦截.
范例:针对于返回结果拦截
package cn.zwb.aop; import org.springframework.stereotype.Component; @Component public class ServiceAspect { public void serviceBefore(){ System.out.println("AO切面 执行日志记录操作"); } public void serviceBefore2(Object vo){ System.out.println("AO切面 执行增加前的一个操作.参数="+vo); } public void serviceAfter(){ System.out.println("AOP切面 执行事务处理操作"); } public void serviceAfterReturning(Object val){ System.out.println("AOP切面 操作完成返回结果:"+val); } }
但是此时依然需要在applicationContext.xml文件里面配置操作形式
范例:修改applicationContext文件
<aop:config proxy-target-class="true"> <!-- 首先定义程序的切入点 --> <aop:pointcut expression="execution(* cn.zwb..*.*(..)) and args(abc)" id="pointcut"/> <!-- 定义要使用的面向切面的处理类 --> <aop:aspect ref="serviceAspect"> <aop:before method="serviceBefore2" pointcut-ref="pointcut" arg-names="abc"/> <aop:after method="serviceAfter" pointcut="execution(* cn.zwb..*.*(..))"/> <aop:after-returning method="serviceAfterReturning" pointcut="execution(* cn.zwb..*.*(..))" arg-names="abc" returning="abc"/> </aop:aspect> </aop:config>
处理返回结果的拦截之外,还可以进行异常处理的拦截操作.
范例:修改一下MemberServiceIm的方法
package cn.zwb.service.impl; import org.springframework.stereotype.Service; import cn.zwb.service.IMemberService; import cn.zwb.vo.Member; @Service public class MemberServiceImpl implements IMemberService{ @Override public boolean insert(Member vo) { throw new NullPointerException("我就是抛个异常"); // System.out.println("数据层调用member="+vo); // return false; } }
那么随后需要增加新的拦截处理方法操作
范例:修改ServiceAspect程序类
package cn.zwb.aop; import org.springframework.stereotype.Component; @Component public class ServiceAspect { public void serviceBefore(){ System.out.println("AO切面 执行日志记录操作"); } public void serviceBefore2(Object vo){ System.out.println("AO切面 执行增加前的一个操作.参数="+vo); } public void serviceAfter(){ System.out.println("AOP切面 执行事务处理操作"); } public void serviceAfterReturning(Object val){ System.out.println("AOP切面 操作完成返回结果:"+val); } public void AfterThrowing(Exception ex){ System.out.println("AOP切面 操作出现异常:"+ex); } }
同时修改applicationContext.xml文件
<aop:after-throwing method="AfterThrowing" pointcut="execution(* cn.zwb..*.*(..))" arg-names="aa" throwing="aa"/>
理论上而言,以上的几个拦截器已经可以成功的覆盖掉了所有的AOP可以处理的范畴,但是为了考虑到简化问题,在我们整个的AOP处理之中,又提供有一种环绕通知,即:可以一个方法处理所有的AOP操作,但是操作更像代理结构.
范例:修改ServiceAspect类增加环绕处理;
但是在进行环绕处理的时候需要注意一点,它必须考虑到接收参数的情况,而接受参数,而接收的参数类型只能够是:ProceedingJoinPoint,通过此类型可以取得全部的提交参数信息.
package cn.zwb.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.stereotype.Component; import cn.zwb.vo.Member; @Component public class ServiceAspect { public void serviceBefore(){ System.out.println("AO切面 执行日志记录操作"); } public void serviceBefore2(Object vo){ System.out.println("AO切面 执行增加前的一个操作.参数="+vo); } public void serviceAfter(){ System.out.println("AOP切面 执行事务处理操作"); } public void serviceAfterReturning(Object val){ System.out.println("AOP切面 操作完成返回结果:"+val); } public void AfterThrowing(Exception ex){ System.out.println("AOP切面 操作出现异常:"+ex); } public Object serviceAroud(ProceedingJoinPoint point) throws Throwable{ System.out.println("AOP切面 数据层方法调用之前,参数:"+point.getArgs()); Member vo=new Member(); vo.setMid("啊大叔说的"); vo.setName("非绯闻绯闻"); Object retval=point.proceed(new Object[]{vo});//调用具体的真实操作 System.out.println("AOP切面 数据层方法调用之后,返回值:"+retval); return true; //可以自己修改返回值 } }
在整个环绕拦截之中,用户可以任意的修改传递的参数数据,也可以修改返回的结果.
范例:在applicationContext.xml文件之中配置环绕拦截
<aop:around method="serviceAroud" pointcut="execution(* cn.zwb..*.*(..))"/>
在整个给出的AOP操作之中,环绕通知的操作应该是功能最强大的,其它的拦截都只能够做一些基础的信息记录,而环绕甚至可以对传入参数和结果进行控制.