当前位置: 首页 > news >正文

24.12.25 AOP

  • 前置通知
  • 环绕通知
  • 后置通知
  • 最终通知
  • 异常通知

API类似,只是生效的时机不一样,并且,不能保证,各个通知的顺序

try {//前置通知before();//环绕通知,内部是执行的方法around(proxy,method,args,methodProxy);//后置通知afterReturn();
} catch (Throwable e) {exception();//异常通知
}finally {after();//最终通知
}

前置通知

被访问的方法,执行之前执行的通知

先执行通知的方法,然后再执行被访问的方法本身

public void f2(JoinPoint joinPoint){
System.out.println("----------前置通知");
//被访问方法的参数
Object[] args = joinPoint.getArgs();
//被访问方法所在类的,bean对象
Object target = joinPoint.getTarget();
//被访问的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
System.out.println(method.getName()+"被调用了,传入了参数:"+ Arrays.toString(args)+"---所在类:"+target);
}

环绕通知

public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("==========环绕通知开始=========");//调用方法,必须写的,如果不写,目标方法不会被调用//Object o 是被执行方法的返回值Object o = joinPoint.proceed();//MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();Object[] args = joinPoint.getArgs();//method.invoke(12);System.out.println("==========环绕通知结束========="+method.getName());return o;
}
  • 配置通知
<aop:aspect ref="test1"><!--前置通知,在切入点的方法,被访问之前,执行的方法--><aop:before method="f2" pointcut-ref="q3"/><aop:around method="aroundMethod" pointcut-ref="q3"/><aop:after-throwing method="f3" pointcut-ref="q3"/><aop:after method="f4" pointcut-ref="q3"/><aop:after-returning method="f5" pointcut-ref="q3"/>
</aop:aspect>

SpringAOP原理

动态代理

注解AOP

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"
><context:component-scan base-package="com.javasm"/><!--开启AOP注解--><aop:aspectj-autoproxy/>
</beans>
//<aop:aspect ref='aspect2'>
@Component("aspect2")
@Aspect
public class TestAspect2 {//切点,标记@Pointcut("execution(* com.javasm.*.service.*.*.query*(..))")void f1(){}@Before("f1()")void before(JoinPoint joinPoint){System.out.println("注解前置通知");}@Around("f1()")Object aroundTest(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("-----环绕通知开始");Object proceed = joinPoint.proceed();System.out.println("------环绕通知结束");return proceed;}@After("f1()")void after(JoinPoint joinPoint){System.out.println("========最终通知");}//@AfterReturning("f1()")@AfterReturning(value = "f1()",returning = "msg")void afterReturn(JoinPoint joinPoint,Object msg){System.out.println("##########后置通知########返回值:"+msg);}//@AfterThrowing("f1()")@AfterThrowing(value = "f1()",throwing = "e")void afterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("=========异常通知:"+e);}
}

自定义注解

自定义注解搭配AOP注解,灵活的控制方法

案例:

想在项目中记录日志

但是不是每个模块每个方法都记录

哪个方法需要记录,现在还不确定,但是要提前把业务逻辑写好

利用自定义注解,哪个方法需要增加日志,就在哪个方法上面加上自定义注解

  • 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SaveLog {//String value();
}
  • 切面类
@Component
@Aspect
public class SaveLogAspect {@ResourceLogService logService;//方法执行结束之后,保存日志@AfterReturning("@annotation(com.javasm.aspect.SaveLog)")public void saveLog(JoinPoint joinPoint){String msg = "%s方法,在%s时间,被调用了,参数是%s";//方法MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();String methodName = method.getName();//时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String time = simpleDateFormat.format(new Date());//参数String parameters = Arrays.toString(joinPoint.getArgs());msg = String.format(msg,methodName,time,parameters);logService.save(msg);}
}

@SaveLog

  • 控制到类

案例:

统计方法运行消耗的时间

统计某一个类所有的方法

@within必须是在类级别生效

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Time {
}
@Component
@Aspect
public class TimeAspect {@Around("@within(com.javasm.aspect.Time)")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {long start = System.currentTimeMillis();Object proceed = joinPoint.proceed();long time = System.currentTimeMillis() - start;String msg = "%s方法,运行消耗的时间是%s毫秒";MethodSignature signature = (MethodSignature) joinPoint.getSignature();String methodName = signature.getMethod().getName();System.out.printf(msg,methodName,time);return proceed;}
}

@Time

配置类启动

@Configuration
@ComponentScan("com.javasm")
@EnableAspectJAutoProxy//开启注解AOP
public class JavasmConfig {}
AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext(JavasmConfig.class);


http://www.mrgr.cn/news/81231.html

相关文章:

  • 在 Vue3 项目中安装和配置 Three.js
  • 搭建一个简单的Web服务器(Apache2.4)
  • Odoo 免费开源 ERP:通过 JavaScript 创建对话框窗口的技术实践分享
  • 《操作系统真象还原》第十章(一) —— 同步机制之互斥锁的实现
  • 重拾设计模式--迭代器模式
  • 备忘一个FDBatchMove数据转存的问题
  • 【C++】模板与泛型编程(一):定义模板,控制实例化、效率与灵活性
  • NLP 中文拼写检测纠正论文-02-2019-SOTA FASPell Chinese Spell Checke github 源码介绍
  • 本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——12使用YOLO-Bin
  • MacroSan 2500_24A配置
  • 重温设计模式--工厂模式(简单、工厂、抽象)
  • Genesis世界模型的上手与测试
  • 【蓝桥杯——物联网设计与开发】拓展模块4 - 脉冲模块
  • 一起学Git【第五节:git版本回退】
  • js的节流与防抖方法封装
  • 大数据实验三
  • 重温设计模式--组合模式
  • 百度慧眼百度热力图数据处理,可直接用于论文
  • 如何与AI对话,写好Prompt
  • 重温设计模式--观察者模式
  • Vulhub靶场Apache漏洞
  • 华为实训课笔记 2024 1223-1224
  • nginx—rewrite功能
  • NS3学习——队列管理机制
  • 题解 洛谷 Luogu P1135 奇怪的电梯 广度优先搜索 BFS C/C++
  • Debian环境安装Docker Engine