zoukankan      html  css  js  c++  java
  • Spring AOP基础

    AOP基本术语

    Advice-通知

    Before

    前置通知,目标方法被调用前调用

    After

    后置通知,目标方法完成后调用通知,并不关心方法的输出是什么

    After-returning

    目标方法成功执行后调用

    After-throwing

    目标方法抛出异常后调用

    Around

    通知包裹了被通知的方法,在被通知的方法调用前和调用后执行自定义行为

    Pointcut-切点

    定义哪些方法是需要被通知的

    Aspect-切面

    Advice+Pointcut=Aspect

    Join Point-连接点

    应用执行过程中能够插入切面的时间点
    如:抛出异常时、调用方法时......

    Introduction-引入

    向现有类添加新的方法或属性

    Weaving-织入

    把切面应用到目标对象并创建新的代理对象

    切点详解

    Spring的AOP中,使用AspectJ切点表达式来定义切点
    Spring仅支持AspectJ切点指示器的一个子集

    arg()

    指定方法的参数类型

    @args()

    指定方法的参数由指定注解标注

    execution()

    指定方法,方法由切点表达式描述 (* 包名.类名.方法名(参数))

    • 表示返回任意类型
      参数如果是 .. ,表示任意参数

    within()

    指定方法类型

    @within()

    指定方法的注解类型

    @annotation()

    指定方法带有指定注解

    其他

    bean()

    bean("beanId")-在指定bean中生效
    !bean("beanId")-在指定bean中不生效

    切点之间可以使用 &&、||、!连接,如果在xml中描述,使用 and、or、not

    定义切面

    package com.zln.aop;
    import org.aspectj.lang.annotation.*;
    /**
     * 定义切面
     * Created by sherry on 17/3/9.
     */
    @Aspect
    public class Audience {
        /**
         * 切点
         */
        @Pointcut("execution(* com.zln.aop.Performance.*(..))")
        public void performance(){}
        /**
         * 前置通知
         */
        @Before("performance()")
        public void silenceCellPhones(){
            System.out.println("前置通知:表演前手机静音");
        }
        @Before("performance()")
        public void takeSeats(){
            System.out.println("前置通知:就坐");
        }
        @AfterReturning("performance()")
        public void applause(){
            System.out.println("返回通知:表演结束,鼓掌");
        }
        @AfterThrowing("performance()")
        public void demandRefund(){
            System.out.println("异常通知:表演失败");
        }
    }
    
    package com;
    import com.zln.aop.Audience;
    import org.springframework.context.annotation.*;
    /**
     * Created by sherry on 17/3/9.
     */
    @Configuration
    @EnableAspectJAutoProxy
    @ComponentScan
    public class AppBeans {
        @Bean
        public Audience audience(){
            return new Audience();
        }
    }
    
    

    运行测试

    package com.zln.aop;
    import org.springframework.stereotype.Component;
    /**
     * Created by sherry on 17/3/9.
     */
    @Component
    public class Performance{
        public void perform() {
            System.out.println("正在表演");
        }
    }
    

    环绕通知

    package com.zln.aop;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    /**
     * 定义切面
     * Created by sherry on 17/3/9.
     */
    @Aspect
    public class Audience {
        /**
         * 切点
         */
        @Pointcut("execution(* com.zln.aop.Performance.*(..))")
        public void performance(){}
        /**
         * 前置通知
         */
        @Before("performance()")
        public void silenceCellPhones(){
            System.out.println("前置通知:表演前手机静音");
        }
        @Before("performance()")
        public void takeSeats(){
            System.out.println("前置通知:就坐");
        }
        @AfterReturning("performance()")
        public void applause(){
            System.out.println("返回通知:表演结束,鼓掌");
        }
        @AfterThrowing("performance()")
        public void demandRefund(){
            System.out.println("异常通知:表演失败");
        }
        @Around("performance()")
        public void watch(ProceedingJoinPoint proceedingJoinPoint){
            System.out.println("环绕通知1");
            try {
                proceedingJoinPoint.proceed();
                System.out.println("环绕通知2");
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }
    

    环绕通知的proceedingJoinPoint.proceed();比较神奇,如果没有这句,相当于代码阻塞,如果调用多次,相当于执行多次目标方法

    通知的方法参数

    package com.zln.aop;
    import org.springframework.stereotype.Component;
    /**
     * Created by sherry on 17/3/9.
     */
    @Component
    public class Performance{
        public void perform(int i) {
            System.out.println("正在表演");
        }
    }
    
        //如果不是int等基本类型,要使用类的全限定名
        @Pointcut("execution(* com.zln.aop.Performance.*(int))")
        public void performance(){}
        /**
         * 前置通知
         */
        @Before("performance()&&args(i)")
        public void silenceCellPhones(int i){
            System.out.println("前置通知:表演前手机静音"+i);
        }
    

    调用perform方法的时候,参数i的值就会被获取到

  • 相关阅读:
    Java反射(2)访问字段(Field)
    《编程珠玑》中“位图排序”引发的一系列实验
    Java : 传值or传引用?
    const 指针
    三种数据库访问——Spring3.2 + Hibernate4.2
    三种数据库访问——Spring JDBC
    数据库连接池:Druid
    三种数据库访问——原生JDBC
    介绍4款json的java类库 及 其性能测试
    云存储(Swift+Keystone)部署策略
  • 原文地址:https://www.cnblogs.com/sherrykid/p/7058008.html
Copyright © 2011-2022 走看看