Spring基於註解@AspectJ的AOP

Spring除了支持XML方式配置AOP,還支持註解方式:使用@AspectJ風格的切面聲明。

但是用註解方式需要在XML啓用對@AspectJ的支持,將在Spring上下文創建一個AnnotationAwareAspectJAutoProxyCreator類,它會自動代理一些Bean,這些Bean的方法需要與使用@Aspect註解的Bena中所定義的切點相匹配,而這些切點又是使用@Pointcut註解定義出來的,下面來看下例子(PS:我的例子都沒有攜帶參數):

聲明切入點
@AspectJ風格的命名切入點使用org.aspectj.lang.annotation包下的@Pointcut方法(方法必須是返回void類型)實現。
@Pointcut(value=”切入點表達式”, argNames = “參數名列表”)
public void pointcutName(……) {}

聲明通知

前置通知
使用org.aspectj.lang.annotation 包下的@Before註解聲明;
@Before(value = “切入點表達式或命名切入點”, argNames = “參數列表參數名”)

後置返回通知
使用org.aspectj.lang.annotation 包下的@AfterReturning註解聲明;
@AfterReturning(
value=”切入點表達式或命名切入點”,
pointcut=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”,
returning=”返回值對應參數名”)

後置最終通知
使用org.aspectj.lang.annotation 包下的@After註解聲明;
@After (
value=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”)

後置異常通知
使用org.aspectj.lang.annotation 包下的@AfterThrowing註解聲明
@AfterThrowing (
value=”切入點表達式或命名切入點”,
pointcut=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”,
throwing=”異常對應參數名”)

[java]

    package cn.com.ztz.spring.service;    

    public interface ShowService {    
        public void show();    
    } 

[java]

    package cn.com.ztz.spring.service;    

    public class ShowServiceImpl implements ShowService{    
        @Override    
        public void show() {      
            showBefore();    
            //showError();//異常測試 (後置異常通知)   
            showEnd();    
        }    
        public void showBefore(){    
            System.out.println("showBefore============");    
        }    
        public void showError(){    
            System.out.println("showError============");    
            throw new RuntimeException();    
        }    
        public void showEnd(){    
            System.out.println("showEnd===============");    
        }    
    } 

[java]

    package cn.com.ztz.spring.service;  

    import org.aspectj.lang.annotation.AfterReturning;  
    import org.aspectj.lang.annotation.AfterThrowing;  
    import org.aspectj.lang.annotation.Aspect;  
    import org.aspectj.lang.annotation.Before;  
    import org.aspectj.lang.annotation.Pointcut;  

    @Aspect  
    public class AudienceAspect {  
        //定義切點  
        @Pointcut("execution(* cn.com.ztz.spring.service.ShowServiceImpl.show(..))")  
        public void performance(){  
            //該方法的內容不重要,該方法的本身只是個標識,供@Pointcut註解依附  
        }  
        //前置通知  
        @Before("performance()")  
        public void taskSeats(){    
            System.out.println("等候節目開始===");    
        }    
        //後置通知  
        @After("performance()")  
        public void applaud(){    
            System.out.println("鼓掌=========");    
        }  
        //後置異常通知  
        @AfterThrowing("performance()")  
        public void demandRefund(){    
            System.out.println("退錢離場======");    
        }    
    }

[html]

    <!-- 啓用@AspectJ支持 -->  
    <aop:aspectj-autoproxy/>  
    <bean id="show" class="cn.com.ztz.spring.service.ShowServiceImpl"/>  
    <bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>  

[java] 

public static void main(String[] args) {  
            ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");      
            ShowService hs = ctx.getBean("show", ShowService.class);      
            System.out.println("======================================");    
            hs.show();   
            System.out.println("======================================");   
        } 

運行測試方法控制檯輸出:

======================================
等候節目開始===
showBefore============
showEnd===============
鼓掌 ========

======================================

註解環繞通知

像Spring基於XML的AOP一樣,@AspectJ註解的使用不僅只限定與定義前置和後置通知類型。我們還可以創建環繞通知,使用環繞通知需要使用@Around。

@Around (
value=”切入點表達式或命名切入點”,
argNames=”參數列表參數名”)

[java]


  public interface ShowService {    
        public void show(String param);    
    }  



[java] 


    @Override    
  public void show(String param) {  
            System.out.println("around==========="+param);   
        } 

[java]

    @Aspect  
   public class AudienceAspect {  
        //定義切點  
        @Pointcut("execution(* cn.com.ztz.spring.service.ShowServiceImpl.show(..))")  
   public void performance(){  
            //該方法的內容不重要,該方法的本身只是個標識,供@Pointcut註解依附  
        }  
        @Around("performance()")  
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {      
            System.out.println("around before advice===========");      
            Object retVal = pjp.proceed(new Object[] {"around"});      
            System.out.println("around after advice===========");      
            return retVal;     
        }  
    }

運行測試方法控制檯輸出:

======================================
around before advice===========
around===========around
around after advice===========

======================================

引入
@AspectJ風格的引入聲明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents聲明

@DeclareParents(
value=”AspectJ語法類型表達式”,
defaultImpl=”引入接口的默認實現類”)
[java]

    package cn.com.ztz.spring.service;  

    public interface DeclareService {    
        public void declare();    
    }

[java]

    package cn.com.ztz.spring.service;  
    public class DeclareServiceImpl implements DeclareService {    
        @Override    
        public void declare() {    
            System.out.println("declare=====================");    
        }    
    }  

[java]

    package cn.com.ztz.spring.service;  

    import org.aspectj.lang.annotation.Aspect;  
    import org.aspectj.lang.annotation.DeclareParents;  

    @Aspect  
    public class AudienceAspect {  
        @DeclareParents(value="cn.com.ztz.spring.service.ShowServiceImpl+",  
                defaultImpl=cn.com.ztz.spring.service.DeclareServiceImpl.class)  
        private DeclareService declareService;} 

[java]

 public static void main(String[] args) {  
            ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");      
            DeclareService hs = ctx.getBean("show", DeclareService.class);      
            System.out.println("======================================");    
            hs.declare();   
            System.out.println("======================================");   
        }  

運行測試方法輸出結果:

======================================
declare=====================

======================================

發佈了71 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章