Spring學習日記(二)AOP的深入操作
阿新 • • 發佈:2018-12-31
上次的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、執行結果