AOP基礎:注解方式實現前置通知、后置通知、環繞通知、異常通知、最終通知(demo)


除了使用xml配置外,還可以使用注解的方式實現上述幾種通知。

 

LogAspectAnnotation.java:

package aop.Aspe;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component("logAnn")
@Aspect
public class LogAspectAnnotation {
    @Before("execution(public * springProject.Student.add(..))")
    public void bBefore() {
        System.out.println("@@@前置通知");
    }
    @AfterReturning("execution(public * springProject.Student.add(..))")
    public void bAfter() {
        System.out.println("@@@后置通知");
    }
    @AfterThrowing("execution(public * springProject.Student.add(..))")
    public void bThrowing() {
        System.out.println("@@@異常通知");
    }
    
    //環繞通知 ,參數ProceedingJoinPoint
    @Around("execution(public * springProject.Student.add(..))")
    public void myAround(ProceedingJoinPoint jp  ) {
        //方法之前:前置通知
        System.out.println("《【環繞】方法之前:前置通知");
        
        try {
            //方法執行時
            jp.proceed() ;//執行方法
    
            //方法之前之后:后置通知
            System.out.println("《【環繞】方法之前之后:后置通知");
        }catch(Throwable e) {
            //發生異常時:異常通知
            System.out.println("《【環繞】發生異常時:異常通知");
        }finally {
            //最終通知
            System.out.println("《【環繞】最終通知");
        }
    }
}

 

tips:

@Component("logAnn"): 把這個類加入ioc容器,id為logAnn。
    必須在xml中,加入xmlns:context="http://www.springframework.org/schema/context"
    然后調用掃描器:<context:component-scan base-package="aop.Aspe"></context:component-scan>
    掃描器 會將 指定的包 中的  @Componet @Service  @Respository   @Controller修飾的類產生的對象 增加到IOC容器中

@Aspect:  聲明這個類是個通知。
       不需要通過掃描器,只需要在xml文件中開啟即可:<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

@Before("execution(public * springProject.Student.add(..))")
       聲明這個方法是個前置通知,關聯的業務方法為add。

@AfterReturning("execution(public * springProject.Student.add(..))")
       
聲明這個方法是個前置通知,關聯的業務方法為add。

@AfterThrowing("execution(public * springProject.Student.add(..))")  
       聲明這個方法是個異常通知。
@Around("execution(public * springProject.Student.add(..))")
       聲明這個方法為環繞通知。

上述各個通知對應的方法名可以隨便取。


如果想要獲取目標對象的一些參數,則需要使用一個對象:JointPoint。

package org.lanqiao.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
//<bean id="logAnnotation" class="org.lanqiao.aop.LogAspectAnnotation">
//@Component("logAnnotation")   //將LogAspectAnnotation納入springIOC容器中
@Aspect //此類是一個通知
public class LogAspectAnnotation  {
    
    //前置通知
    @Before("execution(public * addStudent(..))") //屬性:定義切點
    public void myBefore(JoinPoint jp) {
        System.out.println("《注解形式-前置通知》:目標對象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName() +",參數列表:"+ jp.getArgs().length  );
    }
    //后置通知
    @AfterReturning( pointcut= "execution(public * addStudent(..))" ,returning="returningValue" ) 
    public void myAfter(JoinPoint jp,Object returningValue) {//returningValue是返回值,但需要告訴spring
        System.out.println("《注解形式-后置通知》:目標對象:"+jp.getTarget()+",方法名:"+jp.getSignature().getName() +",參數列表:"+  jp.getArgs().length+",返回值:"+returningValue );
    }
    
    /*環繞通知 ,參數ProceedingJoinPoint
    @Around("execution(public * addStudent(..))")
    public void myAround(ProceedingJoinPoint jp  ) {
        //方法之前:前置通知
        System.out.println("《【環繞】方法之前:前置通知");
        
        try {
            //方法執行時
            jp.proceed() ;//執行方法
    
            //方法之前之后:后置通知
            System.out.println("《【環繞】方法之前之后:后置通知");
        }catch(Throwable e) {
            //發生異常時:異常通知
            System.out.println("《【環繞】發生異常時:異常通知");
        }finally {
            //最終通知
            System.out.println("《【環繞】最終通知");
        }
    }*/
    
    //異常通知:如果只捕獲特定類型的已存銀行,則可以通過第二個參數實現:e
    @AfterThrowing(pointcut= "execution(public * addStudent(..))",throwing="e")
    public void myException(JoinPoint pj, NullPointerException e) {//此異常通知 只會捕獲NullPointerException類型的異常
        System.out.println("&&&&&&《注解形式-異常通知》----e:"+e.getMessage());
    }
    
    //最終通知
    @After("execution(public * addStudent(..))")
    public void myAfter() {
        System.out.println("《[myAfter]注解形式-最終通知-----通知》----");
    }
    
    
}
 
         
         
        

注解形式的返回值:
a.聲明返回值 的參數名:
  

@AfterReturning( pointcut= "execution(public * addStudent(..))" ,returning="returningValue" ) 
    public void myAfter(JoinPoint jp,Object returningValue) {//returningValue是返回值,但需要告訴spring
    System.out.println("返回值:"+returningValue );

 

b: 注解形式實現aop時,通知的方法的參數不能多、少。

c: 實現接口形式、注解形式 只捕獲聲明的特定類型的異常,而其他類型異常不捕獲。

d: 異常通知,可以只在某個特定異常才輸出。

@AfterThrowing(pointcut= "execution(public * addStudent(..))",throwing="e")
  public void myException(JoinPoint pj, NullPointerException e) {//此異常通知 只會捕獲NullPointerException類型的異常
  System.out.println("&&&&&&《注解形式-異常通知》----e:"+e.getMessage());
}

 

 

 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM