在之前只是进行了最为简单的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操作之中,环绕通知的操作应该是功能最强大的,其它的拦截都只能够做一些基础的信息记录,而环绕甚至可以对传入参数和结果进行控制.