• spring12----基于@AspectJ的AOP


    Spring除了支持Schema方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明。

    一. 启用对@AspectJ的支持

     Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置

    <aop:aspectj-autoproxy/>

    二. 声明切面

    @AspectJ风格的声明切面非常简单,使用@Aspect注解进行声明:

    @Aspect() 
    Public class Aspect{
    ……
    }

    然后将该切面在配置文件中声明为Bean后,Spring就能自动识别并进行AOP方面的配置:

    <bean id="aspect" class="……Aspect"/>

    三. 声明切入点

    @AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必须是返回void 类型)实现。

    @Pointcut(value="切入点表达式", argNames = "参数名列表")
     public void pointcutName(……) {
     }

    value:指定切入点表达式;
    argNames:指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同 名的参数,同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。
    pointcutName:切入点名字,可以使用该名字进行引用该切入点表达式。

    @Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")  
    public void beforePointcut(String param) {}  

    说明:定义了一个切入点,名字为“beforePointcut”,该切入点将匹配目标方法的第一个参数类型为通知方法实现中参数 名为“param”的参数类型。

    四. 声明通知

    @AspectJ风格的声明通知也支持5种通知类型:

    1. 前置通知

    使用org.aspectj.lang.annotation 包下的@Before注解声明;

    @Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")

    value:指定切入点表达式或命名切入点;
    argNames:与Schema方式配置中的同义。

    举例:

    1 public interface IHelloWorldService {
    2     public void sayAdviserBefore(String param);
    3 }
    View Code
     1 package com.test.spring.service.impl;
     2 
     3 
     4 import com.test.spring.service.IHelloWorldService;
     5 
     6 public class HelloWorldService implements IHelloWorldService{
     7     public void sayAdviserBefore(String param) {
     8         
     9     }
    10 }
    View Code
    @Aspect
    public class HelloWorldAspect2 {
        @Pointcut(value="execution(* com.test.spring.service.impl..*.sayAdviserBefore(..)) && args(param)", argNames = "param")  
        public void beforePointcut(String param) {
        }
        
        @Before(value = "beforePointcut(param)", argNames = "param")  
        public void beforeAdvice(String param) {  
            System.out.println("===========before advice param:" + param);  
        } 
        
    
    }
    <aop:aspectj-autoproxy/>
        <bean id="helloWorldService"
            class="com.test.spring.service.impl.HelloWorldService" />
        <bean id="aspect" class="com.test.spring.aop.HelloWorldAspect2" />
     1 public class AopTest {
     2     @Test
     3     public void test() {
     4         ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
     5         IHelloWorldService helloWorldService=(IHelloWorldService) context.getBean("helloWorldService");
     6         helloWorldService.sayAdviserBefore("hahah");
     7     }
     8 }
     9 
    10 
    11 ===========before advice param:hahah
    View Code

    分析:

    切面、切入点、通知全部使用注解完成:
    1)使用@Aspect将POJO声明为切面;
    2)使用@Pointcut进行命名切入点声明,同时指定目标方法第一个参数类型必须是java.lang.String,对于其他 匹配的方法但参数类型不一致的将也是不匹配的,通过argNames = "param"指定了将把该匹配的目标方法参数传递 给通知同名的参数上;
    3)使用@Before进行前置通知声明,其中value用于定义切入点表达式或引用命名切入点;
    4)配置文件需要使用<aop:aspectj-autoproxy/>来开启注解风格的@AspectJ支持;
    5)需要将切面注册为Bean,如“aspect”Bean;
    6)测试代码完全一样。

    2. 后置返回通知

    使用org.aspectj.lang.annotation 包下的@AfterReturning注解声明;

    @AfterReturning(  
    value="切入点表达式或命名切入点",  
    pointcut="切入点表达式或命名切入点",  
    argNames="参数列表参数名",  
    returning="返回值对应参数名")  

      value指定切入点表达式或命名切入点;

      pointcut同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;

      argNames与Schema方式配置中的同义;

      returning与Schema方式配置中的同义。

    @AfterReturning(  
        value="execution(* cn.javass..*.sayBefore(..))",  
        pointcut="execution(* cn.javass..*.sayAfterReturning(..))",  
        argNames="retVal", returning="retVal")  
    public void afterReturningAdvice(Object retVal) {  
        System.out.println("===========after returning advice retVal:" + retVal);  
    }  

    3. 后置异常通知

    三、后置异常通知:

    使用org.aspectj.lang.annotation 包下的@AfterThrowing注解声明;

    @AfterThrowing (  
    value="切入点表达式或命名切入点",  
    pointcut="切入点表达式或命名切入点",  
    argNames="参数列表参数名",  
    throwing="异常对应参数名")  

           value指定切入点表达式或命名切入点;

           pointcut同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;

           argNames与Schema方式配置中的同义;

           throwing与Schema方式配置中的同义。

    @AfterThrowing(  
        value="execution(* cn.javass..*.sayAfterThrowing(..))",  
        argNames="exception", throwing="exception")  
    public void afterThrowingAdvice(Exception exception) {  
        System.out.println("===========after throwing advice exception:" + exception);  
    }  

    四. 后置最终通知

    使用org.aspectj.lang.annotation 包下的@After注解声明

    @After (  
    value="切入点表达式或命名切入点",  
    argNames="参数列表参数名")  

           value指定切入点表达式或命名切入点;

           argNames与Schema方式配置中的同义;

    @After(value="execution(* cn.javass..*.sayAfterFinally(..))")  
    public void afterFinallyAdvice() {  
        System.out.println("===========after finally advice");  
    }  

    5. 环绕通知

    使用org.aspectj.lang.annotation 包下的@Around注解声明

    @Around (  
    value="切入点表达式或命名切入点",  
    argNames="参数列表参数名")  

           value指定切入点表达式或命名切入点;

           argNames与Schema方式配置中的同义;

    @Around(value="execution(* cn.javass..*.sayAround(..))")  
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {  
        System.out.println("===========around before advice");  
        Object retVal = pjp.proceed(new Object[] {"replace"});  
        System.out.println("===========around after advice");  
        return retVal;  
    }  

    参考文献

    https://jinnianshilongnian.iteye.com/blog/1420689

  • 相关阅读:
    redis学习笔记(5)hash类型
    redis学习笔记(4)set集合
    redis学习笔记(3)list数据类型
    redis学习笔记(7)配置文件说明
    Uipath学习(1):Uipath变量及数据类型
    Novice学Pytest(4)fixture的详细使用
    Novice学Pytest(3)setup和teardown执行顺序
    Novice学Pytest(1)快速入门
    用python3脚本把labelme的json格式文件转png/xml格式文件
    Ubuntu18.04 安装NVIDIA显卡驱动(GTX1060)+CUDA10.1+CUDNNv8+Anaconda3+pytorch+pycharm (最全教程,踩坑)
  • 原文地址:https://www.cnblogs.com/Hermioner/p/10202374.html
Copyright © 2020-2023  润新知