2、Spring-AOP

1、面向切面编程AOP
  AOP:解耦,一组类共享相同的行为
  Spring只支持方法拦截的AOP,即拦截发最小粒度为类中方法
  术语:
  切面Aspect:在一个什么样的环境中工作,动态代理中可以理解为一个拦截器
  通知Advice:切面的方法,类比拦截器中的方法
    前置通知before
    后置通知after
    返回通知afterReturning
    异常通知afterThrowing
    环绕通知around
  引入Introduction:在现有的类里添加自定义类和方法
  切点Pointcut:限定什么时候启动拦截并织入对应的流程中
  连接点join point:具体要拦截的东西,可以通过切点的正则表达式去判断哪些方法是连接点
  织入Weaving:生成代理对象并将切面内容放入到流程中的过程
    Spring是以JDK的CGLIB动态代理来生成代理对象
2、AspectJ注解式切面编程
  基于注解拦截
  基于方法规则拦截
3、AspectJ注解
  @EnableAspectJAutoProxy:开启Spring对AspectJ的支持,注意,该注解是放在配置类上的
  @Aspect:声明是一个切面
  @PointCut:声明切点

  通知类型:
  @Before:前置通知,被代理对象的方法前调用
  @After:后置通知,被代理对象的方法后调用
  @AfterReturning:返回通知,要求被代理对象的方法执行过程中没有发生异常,方法正常返回后调用
  @AfterThrowing:异常通知,要求被代理对象的方法执行过程中产生异常,方法抛出异常后调用
  @Around:环绕通知
4、切点定义
  常用的基于方法规则的拦截
@Pointcut("execution(* com.ning.ch1.aop.service.FunService.printInputString(..))")
public void methodPointCut() {
};
  execution:限定匹配带有指定注解的连接点
  *:表示任意返回类型的方法,注意,* 后必须有一个空格
  com.ning.xxx...printInputString:被拦截的方法
  连接点的定义很灵活,最小粒度为类,也可以以类、包维度拦截,通过正则表达式可以灵活定义
  printInputString:被拦截的方法
  (..):任意的参数
5、多个切面
  一般情况下,多个切面调用时无序的,也可以指定调用顺序
6、环绕通知及给通知传递参数

 1 import org.aspectj.lang.ProceedingJoinPoint;
 2 import org.aspectj.lang.annotation.Around;
 3 import org.aspectj.lang.annotation.Aspect;
 4 import org.aspectj.lang.annotation.Before;
 5 import org.aspectj.lang.annotation.Pointcut;
 6 import org.springframework.stereotype.Component;
 7 
 8 @Aspect
 9 @Component
10 public class AroundAspect {
11     @Pointcut("execution(* com.ning.ch1.aop.service.DemoAroundService.printInputString(..))")
12     public void aroundPointCut() {
13     };
14     
15     // beforePointCut入参名称要和切点定义中args的参数名称保持一致
16     @Pointcut("execution(* com.ning.ch1.aop.service.DemoAroundService.printInputString02(..)) && args(strff)")
17     public void beforePointCut(String strff) {
18     };
19     
20     @Around("aroundPointCut()")
21     public Object around(ProceedingJoinPoint pjp) {
22         System.out.println("AroundAspect around() before...");
23         // 如果没有返回值,则printInputString()执行也没有返回值
24         Object proceed = null;
25         try {
26             proceed = pjp.proceed();
27         } catch (Throwable e) {
28             e.printStackTrace();
29         }
30         System.out.println("AroundAspect around() after...");
31         return proceed;
32     }
33     
34     // 没必要和beforePointCut参数名称保持一致,此处只要上下一致即可
35     @Before("beforePointCut(strddd)")
36     public void before(String strddd) {
37         // 此处的str获取的是printInputString02()方法的入参实际值
38         System.out.println(strddd);
39         System.out.println("AroundAspect before()");
40     }
41 }

 

posted @ 2019-12-03 21:54  6xiong  阅读(191)  评论(0编辑  收藏  举报