ICode9

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

10分钟入门SpringAOP

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

标签: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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

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

ICode9版权所有