0
点赞
收藏
分享

微信扫一扫

【Spring【AOP】】——20、搭建一个AOP测试环境?

斗米 2022-12-31 阅读 128


📫作者简介:​​zhz小白​​ 公众号:​小白的Java进阶之路​​
专业技能:
1、Java基础,并精通多线程的开发,熟悉JVM原理
2、熟悉Java基础,并精通多线程的开发,熟悉JVM原理,具备⼀定的线上调优经验
3、熟悉MySQL数据库调优,索引原理等,⽇志原理等,并且有出过⼀篇专栏
4、了解计算机⽹络,对TCP协议,滑动窗⼝原理等有⼀定了解
5、熟悉Spring,Spring MVC,Mybatis,阅读过部分Spring源码
6、熟悉SpringCloud Alibaba体系,阅读过Nacos,Sentinel,Seata,Dubbo,Feign,Gateway核⼼源码与设计,⼆次开发能⼒
7、熟悉消息队列(Kafka,RocketMQ)的原理与设计
8、熟悉分库分表ShardingSphere,具有真实⽣产的数据迁移经验
9、熟悉分布式缓存中间件Redis,对其的核⼼数据结构,部署架构,⾼并发问题解决⽅案有⼀定的积累
10、熟悉常⽤设计模式,并运⽤于实践⼯作中
11、了解ElasticSearch,对其核⼼的原理有⼀定的了解
12、了解K8s,Jekins,GitLab
13、了解VUE,GO
14、⽬前有正在利⽤闲暇时间做互游游戏,开发、运维、运营、推销等

本人著作git项目:​​​https://gitee.com/zhouzhz/star-jersey-platform​​​ar
领域:​​对支付(FMS,FUND,PAY),订单(OMS),出行行业等有相关的开发领域​​

文章目录

  • 1、AOP简介
  • 2、作用
  • 3、实现原理
  • 4、优势
  • 5、应用场景
  • 6、AOP相关术语
  • 7、AOP入门实战
  • 7.1、实现AOP打印每个方法结束后打印日志
  • 7.1.1、aop切面类
  • 7.1.2、要被aop的类
  • 7.1.3、MainConfig配置类
  • 7.1.4、测试类
  • 7.1.5、运行结果
  • 8、AOP通知类型
  • 9、AOP切点表达式

1、AOP简介

【Spring【AOP】】——20、搭建一个AOP测试环境?_spring

  • AOP的全称是Aspect Oriented Programming,即面向切面编程。是实现功能统一维护的一种技术,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。

2、作用

  • 在不修改源码的基础上,对已有方法进行增强。

3、实现原理

  • 动态代理技术。

4、优势

  • 减少重复代码、提高开发效率、维护方便

5、应用场景

  • 事务处理
  • 日志管理
  • 权限控制
  • 异常处理等方面。

6、AOP相关术语

名称

说明

Joinpoint(连接点)

指能被拦截到的点,在Spring中只有方法能被拦截。

Pointcut(切点)

指要对哪些连接点进行拦截,即被增强的方法。

Advice(通知)

指拦截后要做的事情,即切点被拦截后执行的方法。

Aspect(切面)

切点+通知称为切面

Target(目标)

被代理的对象

Proxy(代理)

代理对象

Weaving(织入)

生成代理对象的过程

7、AOP入门实战

  • AspectJ是一个基于Java语言的AOP框架,在Spring框架中建议使用AspectJ实现AOP。

7.1、实现AOP打印每个方法结束后打印日志

7.1.1、aop切面类

package com.zhz.aspect;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

import java.util.Date;

/**
* @author zhouhengzhe
* @date 2022/11/19
*/
@Slf4j
@Aspect
public class AopAspect {

/**
* 指定切面的切入点
*/
@Pointcut("execution(* com.zhz.dao.BookDao.*(..))")
public void pointCut() {

}

/**
* 前置通知:执行目标方法前 触发
*/
@Before("pointCut()")
public void logBefore(JoinPoint joinPoint) {
System.out.println("当前时间为:"+(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))+",前置通知——方法名:"+joinPoint.getSignature().getName()+",参数:"+JSON.toJSONString(joinPoint.getArgs()));
}

/**
* 后置通知:执行目标方法后触发
*/
@After(value = "pointCut()")
public void logAfter(JoinPoint joinPoint) {
System.out.println("当前时间为:"+(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))+",后置通知——方法名:"+joinPoint.getSignature().getName()+",参数:"+JSON.toJSONString(joinPoint.getArgs()));

}

/**
* 返回通知:目标方法执行完并返回参数后触发。
*/
@AfterReturning(value = "pointCut()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("当前时间为:"+(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))+",返回通知——方法名:"+joinPoint.getSignature().getName()+",参数:"+JSON.toJSONString(joinPoint.getArgs())+"返回结果:"+ JSON.toJSONString(result));

}

/**
* 异常通知:目标方法抛出异常后触发
*/
@AfterThrowing(value = "pointCut()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
System.out.println("当前时间为:"+(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))+",异常通知——方法名:"+joinPoint.getSignature().getName()+",参数:"+JSON.toJSONString(joinPoint.getArgs())+",异常信息:" + ex.getMessage());
}

/**
* 环绕通知,围绕着方法执行
* 环绕通知需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
* 而且环绕通知必须有返回值,返回值即为目标方法的返回值
*/
@Around(value = "pointCut()")
public Object logAround(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("当前时间为:"+(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"))+",环绕通知前——方法名:"+proceedingJoinPoint.getSignature().getName()+",参数:"+JSON.toJSONString(proceedingJoinPoint.getArgs()));
Object result = null;
//执行目标方法
try {
result = proceedingJoinPoint.proceed();
System.out.println("环绕后");
} catch (Throwable e) {
System.out.println("环绕异常后");
throw new RuntimeException(e);
}
return result;
}
}

7.1.2、要被aop的类

package com.zhz.dao;

import org.springframework.stereotype.Repository;

/**
* @author zhouhengzhe
* @description: todo
* @date 2022/11/4 10:56
* @since v1
*/
@Repository
public class BookDao {
public void add(){
System.out.println("新增图书");
}

public void delete(){
System.out.println("删除图书");
}

public void update(){
System.out.println("更新图书");
}
}

7.1.3、MainConfig配置类

package com.zhz.config;

import com.zhz.aspect.AopAspect;
import com.zhz.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
* @author zhouhengzhe
* @description: todo
* @date 2022/11/4 10:27
* @since v1
*/
@EnableAspectJAutoProxy
@Configuration
public class MainConfig {

@Bean
public BookDao bookDao(){
return new BookDao();
}

// 将切面类加入到容器中
@Bean
public AopAspect aopAspect() {
return new AopAspect();
}
}

7.1.4、测试类

@Test
public void test4(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
BookDao bean = applicationContext.getBean(BookDao.class);
bean.add();
applicationContext.close();
}

7.1.5、运行结果

【Spring【AOP】】——20、搭建一个AOP测试环境?_java_02

8、AOP通知类型

通知类型

描述

前置通知

在方法执行前添加功能

后置通知

在方法正常执行后添加功能

异常通知

在方法抛出异常后添加功能

最终通知

无论方法是否抛出异常,都会执行该通知

环绕通知

在方法执行前后添加功能

9、AOP切点表达式

使用AspectJ需要使用切点表达式配置切点位置,写法如下:

  • 标准写法:访问修饰符 返回值 包名.类名.方法名(参数列表)
  • 访问修饰符可以省略。
  • 返回值使用 * 代表任意类型。
  • 包名使用 * 表示任意包,多级包结构要写多个 * ,使用 *… 表示任意包结构
  • 类名和方法名都可以用 * 实现通配
  • 参数列表
  • 基本数据类型直接写类型
  • 引用类型写 包名.类名
  • ***** 表示匹配一个任意类型参数
  • 表示匹配任意类型任意个数的参数
  • 全通配: *** .*(…)**

举报

相关推荐

0 条评论