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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章