Spring基于注解@AspectJ的AOP

15 篇文章 0 订阅

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=====================

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值