ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

10分钟入门SpringAOP

2021-01-07 09:59:47  阅读:45  来源: 互联网

标签:10 匹配 入门 切面 Aspect SpringAOP execution 方法 public


本篇博文尽力在实际生产和实例代码之间做好平衡,除SpringAOP相关语法知识外,还用到了Lombok的一些注解,并基于Junit进行测试。

导言

AOP相关知识可以看看这篇博文,里面对AOP核心概念做了解释,以下抽出部分核心知识结合SpringAOP做出解释

  1. 切面 Aspect : 在SpringAOP中Aspect就是被@Aspect注解注上的类,其中的撰写Advice通知逻辑。
    1. 通知 Advice : @Around、@After、@Before 等注解注入的对象
    2. 切点 PointCut : 可以使用@PointCut声明,也可以在Advice注解内声明,本文采用后一种方法。
  2. JointPoint 连接点: 在SpringAOP中用于获取被横切点的上下文信息和控制其执行流程对于环绕Advice可以

定义Service

@Service
class ServiceDemo {
    public void doA(String str) {
        System.out.println("i am doAing,str=" + str);
    }

    public void doB() {
        System.out.println("i am doBing");
    }
}

上文代码中定义了两个Service方法,A方法带参,B方法不带参。使用@Service注入IOC容器。

定义日志切面

使用最强大最全面的环绕切面

@Aspect // 声明切面类
@Component //注入IOC
@Slf4j // 日志服务
class AspectDemo {
    @Around("execution(public * ServiceDemo.*(..))") //切面注解
    @SneakyThrows
    public Object logAspect(ProceedingJoinPoint pjp) {
        // 获取方法签名
        String signature = pjp.getSignature().toString();
        // 方法开始前打日志(输出方法引用串和参数列表)
        log.info("{} start,param={}", signature, pjp.getArgs());
        // 调用实际方法
        Object res = pjp.proceed();
        // 方法结束后打日志
        log.info("{} end", signature);
        // 此处的返回值是被切面处理后给客户端的返回值
        return res;
    }
}

所有的切面(Aspect)方法,即被@Around、@After、@Before注上的方法所在的类都需要@Aspect,否则SpringIOC容器不会将该bean识别为切面(SpringAOP基于IOC容器,参考这里)。当然该Aspect类也是需要注入IOC容器的,本Aspect使用@Service注解注入。

对于日志服务,本Aspect使用Lombok的@Slf4j注解,并且因为调用pjp.proceed()会抛出Throwable异常,所以使用lombok的@SneakyThrows注解。

重点介绍下@Around("execution(public * ServiceDemo.*(..))"):

  • @Around声明logAspect方法是环绕通知(Advice),并且使用execution PCDPointCut切面表达式约束了logAspect方法的作用范围: 所有ServiceDemo类的实例下的public方法,匹配任意返回值 ,匹配任意方法名,匹配任意数量参数。

以下就execution PCD做进一步解释

execution PCD(PointCut Designators)

SpringAOP的PCD是完全兼容AspectJ的。

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
          throws-pattern?)
execution(修饰符匹配式? 返回类型匹配式 类名匹配式? 方法名匹配式(参数匹配式) 异常匹配式?)

代码块中带?符号的匹配式都是可选的,对于execution PCD必不可少的只有三个:

  1. 返回值匹配值
  2. 方法名匹配式
  3. 参数匹配式

接下来分析下execution(public * ServiceDemo.*(..)): 该PCD 匹配public修饰符,返回值是*,即任意返回值类型都行,ServiceDemo是类名匹配式只要全局依可见性唯一就行.*是方法名匹配式,匹配所有方法,..是参数匹配式,匹配任意参数数量、任意参数类型的方法。

再举一些其他例子:

  • execution(* com.xyz.service..*.*(..)): 匹配com.xyz.service及其子包下的任意方法。

  • execution(* joke(Object+))):匹配任意名字为joke的方法,且其动态入参是是Object类型或该类的子类。

  • execution(* joke(String,..)):匹配任意名字为joke的方法,该方法 一个入参为String(不可以为子类),后面可以有任意个入参且入参类型不限

  • execution(* com..*.*Dao.find*(..)): 匹配指定包下find开头的方法

  • execution(* com.baobaotao.Waiter+.*(..)) : 匹配com.baobaotao包下Waiter及其子类的所有方法。

SpringAOP其他

更多SpringAOP Advice请看这里,更多PCD语法请看下期。

测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Loader.class)
public class AOPSt1 {
    @Resource
    private ServiceDemo serviceDemo;

    @Test
    @SneakyThrows
    public void test_Aspect() {
        serviceDemo.doA("hello world");
        serviceDemo.doB();
        serviceDemo.doC(1);
    }
}

输出:

image-20210106111120273

总结

SpringAOP切面核心就一个地方: 被@Aspect注解的类,将这个类注入IOC容器中。

之后在其中使用advice注解定义横切逻辑(利用@Around、@After等)。

环绕切面配合ProceedingJoinPoint类使用,其他切面看情况使用JoinPoint或不带参。

参考文章

  1. Spring官方文档
  2. 白话Spring(基础篇)—AOP(execution表达式)

在这里插入图片描述
一键三连吧

标签:10,匹配,入门,切面,Aspect,SpringAOP,execution,方法,public
来源: https://blog.csdn.net/qq_38619183/article/details/112303055

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有