spring-aop-2

1.Declaring Advice(通知)

通知类型:

before 目标方法执行前执行,前置通知
after 目标方法执行后执行,后置通知
after returning 目标方法返回时执行 ,后置返回通知
after throwing 目标方法抛出异常时执行 异常通知
around 在目标函数执行中执行,可控制目标函数是否执行,环绕通知

/**
     * 前置通知
     * @param joinPoint 可以通过joinPoint获取目标对象的一些信息,比如:类名(Method),其中的参数等等
     */
    @Before(value = "execution(* cn.cg.target.IndexDao.*(..))")
    public void before(JoinPoint joinPoint){
        //获取表达式+具体的方法全路径
        System.out.println(joinPoint.toString());
        System.out.println("前置通知"+ Arrays.toString(joinPoint.getArgs()));
    }
    /**
     * 环绕通知
     */
    @Around(value = "execution(* cn.cg.target.IndexDao.*(..))")
    public Object around(ProceedingJoinPoint pjp){
        System.out.println("around-before");
        Object res = null;
        try {
      //目标方法执行 res
= pjp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println("around-after"); return res; } /** * 方法return 前的通知 */ @AfterReturning(value = "execution(* cn.cg.target.IndexDao.*(..))",returning = "resObject") public void afterReturning(Object resObject){ System.out.println("方法返回通知"+resObject); } /** * 方法执行结束 * 类似于finally */ @After(value = "execution(* cn.cg.target.IndexDao.*(..))") public void after(){ System.out.println("后置通知"); } @AfterThrowing( value = "execution(* cn.cg.target.IndexDao.*(..))", throwing="ex") public void afterThrowing(Throwable ex) { System.out.println("抛出异常了"+ex.toString()); }

 

main:

public class MainClass {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
        Dao dao = (Dao) ac.getBean("indexDao");
        System.out.println(dao.query("222", 2));
    }
}

 

console:

  

around-before
execution(String cn.cg.target.Dao.query(String,Integer))
前置通知[222, 2]
around-after
后置通知
方法返回通知2222
2222

执行顺序:

  1.环绕通知 pjp.proccess()方法之前的代码 around

  2.前置通知 before

  3.pjp.proccess() 目标方法 target

  4.环绕通知 pjp.proccess()方法之后的代码 around

   5.后置通知 after

  6.方法return 前的通知   AfterReturning

如果声明多个@Before通知对同一连接点进行增强,执行顺序为代码的声明顺序.

如果是两个不同的切面呢,切面实现Ordered接口,设置优先级

2.Aop简单应用场景

(1)性能监控

切面:

@Component
@Aspect
public class PerformanceMonitoringAspect {
    @Around("execution(* cn.cg.target.IndexDao.query(..))")
    public Object Around(ProceedingJoinPoint pjp) throws Throwable {
        //获取目标类名称
        System.out.print(pjp.getTarget().getClass().getName()+",");
        //获取目标对象方法名
        System.out.print(pjp.getSignature().getName()+",");
        //记录当前时间
        SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println(sim.format(new Date()));
        System.out.println("---------------方法执行-------------------");
        long start = System.currentTimeMillis();
        Object res = pjp.proceed();
        //计算所需时间
        Long end = System.currentTimeMillis();
        System.out.println("---------------方法执行-------------------");
        System.out.println("总用时"+(end-start));
        return res;
    }
}

main:

public class MainClass {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
        Dao dao = (Dao) ac.getBean("indexDao");
        for (int i = 0; i < 3; i++) {
            dao.query("222", 2);
        }
    }
}

console:

  

cn.cg.target.IndexDao,query,2019-07-27
---------------方法执行-------------------
str+i操作进行中...
---------------方法执行-------------------
总用时1
cn.cg.target.IndexDao,query,2019-07-27
---------------方法执行-------------------
str+i操作进行中...
---------------方法执行-------------------
总用时5
cn.cg.target.IndexDao,query,2019-07-27
---------------方法执行-------------------
str+i操作进行中...
---------------方法执行-------------------
总用时3

 

posted @ 2019-07-27 02:37  简单爱1  阅读(209)  评论(0编辑  收藏  举报