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

Java Spring AOP代码3分钟快速入手

AOP

Spring入门(十):Spring AOP使用讲解 - 掘金

maven的依赖:

<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId>
</dependency>
<!--aspectj支持-->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId>
</dependency>

demo1

基于注解实现

AopAnnotation:

package com.example.learn.aop;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface AopAnnotation {
}

TestAspect:

package com.example.learn.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
@Slf4j
public class TestAspect {@Pointcut("@annotation(com.example.learn.aop.AopAnnotation)")private void cut() {}@Around("cut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {log.info("====环绕通知start");// 注解所切的方法所在类的全类名String typeName = joinPoint.getTarget().getClass().getName();log.info("目标对象:[{}]", typeName);// 注解所切的方法名String methodName = joinPoint.getSignature().getName();log.info("所切方法名:[{}]", methodName);StringBuilder sb = new StringBuilder();// 获取参数Object[] arguments = joinPoint.getArgs();for (Object argument : arguments) {sb.append(argument.toString());}log.info("所切方法入参:[{}]", sb.toString());// 统计方法执行时间long start = System.currentTimeMillis();//执行目标方法,并获得对应方法的返回值Object result = joinPoint.proceed();log.info("返回结果:[{}]", result);long end = System.currentTimeMillis();log.info("====执行方法共用时:[{}]", (end - start));log.info("====环绕通知之结束");return result;}}

实现一个被织入的类,注意这个类得是Bean,一般aop都是针对容器的,针对普通类的很少且不常用:

AopClass:

package com.example.learn.aop;import org.springframework.stereotype.Component;@Component
public class AopClass {@AopAnnotationpublic void testAop() {System.out.println("func invoked!");}
}

测试:

正是因为AOP是针对Bean的,因此测试的时候不要像下面这样去测试,因为new出来的这个对象没有被Spring管理:

@SpringBootTest
class LearnApplicationTests {@Testvoid contextLoads() {AopClass aopClass = new AopClass();aopClass.testAop();}}

憨憨行为。应该注入容器来测试:

@SpringBootTest
class LearnApplicationTests {@Autowiredprivate AopClass aopClass;@Testvoid contextLoads() {aopClass.testAop();}}

打印结果:

.   ____          _            __ _ _/\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/  ___)| |_)| | | | | || (_| |  ) ) ) )'  |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot ::                (v2.5.5)2023-10-27 10:56:13.600  INFO 16048 --- [           main] com.example.learn.LearnApplicationTests  : Starting LearnApplicationTests using Java 1.8.0_381 on DESKTOP-NFN5QCN with PID 16048 (started by DELL in F:\OneDrive\Java学习\yunfei\learn)
2023-10-27 10:56:13.604  INFO 16048 --- [           main] com.example.learn.LearnApplicationTests  : No active profile set, falling back to default profiles: default
2023-10-27 10:56:15.202  INFO 16048 --- [           main] com.example.learn.LearnApplicationTests  : Started LearnApplicationTests in 1.916 seconds (JVM running for 2.886)
2023-10-27 10:56:15.408  INFO 16048 --- [           main] com.example.learn.aop.TestAspect         : ====环绕通知start
2023-10-27 10:56:15.408  INFO 16048 --- [           main] com.example.learn.aop.TestAspect         : 目标对象:[com.example.learn.aop.AopClass]
2023-10-27 10:56:15.410  INFO 16048 --- [           main] com.example.learn.aop.TestAspect         : 所切方法名:[testAop]
2023-10-27 10:56:15.410  INFO 16048 --- [           main] com.example.learn.aop.TestAspect         : 所切方法入参:[]
func invoked!
2023-10-27 10:56:15.420  INFO 16048 --- [           main] com.example.learn.aop.TestAspect         : 返回结果:[null]
2023-10-27 10:56:15.420  INFO 16048 --- [           main] com.example.learn.aop.TestAspect         : ====执行方法共用时:[10]
2023-10-27 10:56:15.420  INFO 16048 --- [           main] com.example.learn.aop.TestAspect         : ====环绕通知之结束

demo2

写一个切面类:

package com.example.base.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;@Aspect
public class Detector {@Pointcut("execution(* com.example.base.AopController.hello(..))")public void helloAspect() {}@Before("helloAspect()")public void beforeAction() {System.out.println("before hello~");}@After("helloAspect()")public void afterAction() {System.out.println("after hello~");}@AfterReturning("helloAspect()")public void afterReturningAction() {System.out.println("after return~");}@Around("helloAspect()")public Object aroundAction(ProceedingJoinPoint pjp) throws Throwable {System.out.println("around~");pjp.proceed();System.out.println("around~");return null;}
}

切点为Controller的一个方法:

package com.example.base;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AopController {@GetMapping("/hello")public String hello(@RequestParam("id") int userId) {return null;}
}

写切面的配置类,自动加载切面:

package com.example.base.aop;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class Config {@Beanpublic Detector detector() {return new Detector();}
}

启动项目,浏览器http://localhost:8080/hello?id=1 触发打印:

2023-09-06 15:49:32.974  INFO 198380 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-09-06 15:49:32.974  INFO 198380 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-09-06 15:49:32.975  INFO 198380 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
around~
before hello~
after return~
after hello~
around~
Disconnected from the target VM, address: '127.0.0.1:61026', transport: 'socket'
http://www.lryc.cn/news/322663.html

相关文章:

  • .NET开源快速、强大、免费的电子表格组件
  • docker一键部署若依前后端分离版本
  • Java项目开发之fastjson详解
  • 面试算法-62-盛最多水的容器
  • 【智能算法】海洋捕食者算法(MPA)原理及实现
  • 刷题DAY24 | LeetCode 77-组合
  • Spring Boot为什么默认使用CGLIB动态代理
  • 算法详解——Dijkstra算法
  • 利用GANs进行图像生成
  • Flutter-底部弹出框(Widget层级)
  • 聚焦两会:数字化再加速,VR全景助力制造业转型
  • 数据挖掘之关联规则
  • java:java.util.BitSet对象的Jackson序列化和反序列化实现
  • Go语言学习01-基本程序结构
  • rundeck k8s部署踩坑
  • 每天学习几道面试题|Kafka(二)架构设计类
  • Spring 实现 OAuth2 授权之解决方案
  • el-select使用filterable下拉无法关闭得问题
  • 基于javaweb(springboot)城市地名地址信息管理系统设计和实现
  • vue iframe实现父页面实时调用子页面方法和内容
  • HarmonyOS ArkTS 开发基础/语言
  • AI大模型学习
  • 2024年【T电梯修理】考试内容及T电梯修理作业考试题库
  • 2.vscode 配置python开发环境
  • [蓝桥杯 2015 省 B] 生命之树
  • 为什么Hashtable不允许插入nuIl键和null值?
  • 【WPF应用4】WPF界面对象编辑
  • js数组去重常见方法
  • 【Java Web基础】一些网页设计基础(二)
  • python中tkinter计算器