1. 程式人生 > >Spring學習日記(二)AOP的深入操作

Spring學習日記(二)AOP的深入操作

上次的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、執行結果