(二十五)AOP深入操作

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



猜你喜欢

转载自blog.csdn.net/qq1019648709/article/details/80514087