上次的AOP操作简单,但对初学者而言,删繁就简地体现了aop的设计思想。但有些过于简化了,本次将把参数带入到aop的操作中。
一、前置通知中含参数
1、修改切面处理类:改写serviceBefore(),使其含有参数
public void serviceBefore2(Object arg){
System.out.println("【AOP切面】执行日志记录操作。参数="+ arg);
}
2、修改配置文件:切入点表达式
<aop:config>
<aop:pointcut expression="execution(* cn.mldn..*.*(..)))" id="pointcut"/>
<aop:aspect ref="serviceAspect">
<!-- 重点看pointcut表达式,以及参数的传递 -->
<aop:before method="serviceBefore2" pointcut="execution(* cn.mldn..*.*(..)) and args(vo))" arg-names="vo"/>
<aop:after method="serviceAfter" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
3、运行结果:
【AOP切面】执行日志记录操作。参数=Member [mid=mldn, name=你好]
【数据层调用】member=Member [mid=mldn, name=你好]
【AOP切面】执行事务处理操作
false
二、针对结果拦截
1、修改切面处理类:改写serviceAfter(),使其含有参数
public void serviceAfterReturning(Object val){
System.out.println("【AOP切面】操作完成,返回结果,参数为:"+val);
}
2、修改配置文件:切入点表达式
<aop:config>
<aop:pointcut expression="execution(* cn.mldn..*.*(..)))" id="pointcut"/>
<aop:aspect ref="serviceAspect">
<aop:before method="serviceBefore2" pointcut="execution(* cn.mldn..*.*(..)) and args(vo))" arg-names="vo"/>
<!-- 看这里 -->
<aop:after-returning method="serviceAfterReturning" pointcut-ref="pointcut" returning="haha" arg-names="haha"/>
</aop:aspect>
</aop:config>
3、运行结果:
【AOP切面】执行日志记录操作。参数=Member [mid=mldn, name=你好]
【数据层调用】member=Member [mid=mldn, name=你好]
【AOP切面】操作完成,返回结果,参数为:false
false
三、抛出异常拦截
1、修改MemberServiceImpl.class
public class MemberServiceImpl implements IMemberService {
@Override
public boolean insert(Member vo) {
throw new NullPointerException("Exception occured");
}
}
2、修改切面处理类
public void serviceAfterThrowing(Exception exp) {
System.out.println("【aop切面】操作出现异常,异常为:"+exp);
}
3、修改配置文件:切入点表达式
<aop:config>
<aop:pointcut expression="execution(* cn.mldn..*.*(..)))" id="pointcut"/>
<aop:aspect ref="serviceAspect">
<aop:before method="serviceBefore2" pointcut="execution(* cn.mldn..*.*(..)) and args(vo))" arg-names="vo"/>
<aop:after-returning method="serviceAfterReturning" pointcut-ref="pointcut" returning="haha" arg-names="haha"/>
<!--看这里-->
<aop:after-throwing method="serviceAfterThrowing" pointcut="execution(* cn.mldn..*.*(..)))" arg-names="exp" throwing="exp"/>
</aop:aspect>
</aop:config>
4、运行结果
四、环绕通知
环绕通知:一个方法处理所有操作,这种操作更像代理机构,但注意:要考虑有返回值的情况!!!
1、修改切面处理类:增加环绕处理方法
public Object serviceAround(ProceedingJoinPoint point) throws Throwable{
System.out.println("【AOP切面】数据层方法调用前,参数"+Arrays.toString(point.getArgs()));
Member vo=new Member();
vo.setMid("hello");
vo.setName("world");
Object retVal=point.proceed(new Object[] { vo });
System.out.println("【AOP切面】数据层方法调用之后,返回值:"+retVal);
return true;
}
2、修改配置文件:切入点表达式
<aop:config>
<aop:pointcut expression="execution(* cn.mldn..*.*(..)))" id="pointcut"/>
<aop:aspect ref="serviceAspect">
<aop:around method="serviceAround" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
3、结果:可以说是很强大了!
对传入参数和返回结果可以修改!但这样不好,不建议这么做。
五、通过Annotation配置简化AOP的操作
1、修改配置文件
其他都可以删掉了~
<aop:aspectj-autoproxy/>
2、修改切面处理类
加了很多@XXX
@Component
@Aspect
public class ServiceAspect2 {
@Before(value="execution(* cn.mldn..*.*(..)))")
public void serviceBefore(){
System.out.println("【AOP切面】执行日志记录操作");
}
@Before(value="execution(* cn.mldn..*.*(..)) and args(param)",argNames="param")
public void serviceBefore2(Object arg){
System.out.println("【AOP切面】执行日志记录操作。参数="+ arg);
}
@After(value="execution(* cn.mldn..*.*(..)))")
public void serviceAfter(){
System.out.println("【AOP切面】执行事务处理操作");
}
@AfterReturning(value="execution(* cn.mldn..*.*(..)))",argNames="ret",returning="ret")
public void serviceAfterReturning(Object val){
System.out.println("【AOP切面】操作完成,返回结果,参数为:"+val);
}
@AfterThrowing(value="execution(* cn.mldn..*.*(..)))",argNames="e",throwing="e")
public void serviceAfterThrowing(Exception exp) {
System.out.println("【aop切面】操作出现异常,异常为:"+exp);
}
@Around(value="execution(* cn.mldn..*.*(..)))")
public Object serviceAround(ProceedingJoinPoint point) throws Throwable{
System.out.println("【AOP切面】数据层方法调用前,参数"+Arrays.toString(point.getArgs()));
Member vo=new Member();
vo.setMid("hello");
vo.setName("world");
Object retVal=point.proceed(new Object[] { vo });
System.out.println("【AOP切面】数据层方法调用之后,返回值:"+retVal);
return true;
}
3、运行结果