AspectJ 在 Spring 中的使用

您所在的位置:网站首页 aspectj详解 AspectJ 在 Spring 中的使用

AspectJ 在 Spring 中的使用

2023-09-30 01:01| 来源: 网络整理| 查看: 265

这是一篇纯实例的博客,网络上关于AspectJ的实例博客非常少,很多的博客都是在讲解AOP思想的一些概念以及从AspectJ语言本身出发去讲解AspectJ,但小编觉得作为急需在项目中使用,换句话说对于初学者来说,没有必要从AspectJ语言本身去深入了解它,如果对AOP思想不明白的,请参考我的博客一起来谈谈 Spring AOP!

本文将从AspectJ在Spring中的应用入手讲解。

首先明白一点,AOP思想的实现框架或者说库有很多,最知名的无非就是AspectJ、Cglib、JDK动态代理三种了,归根到底它们都是使用了代理这种设计模式,区别在于下面表格:

名称 代理类型 基本原理 特性 AspectJ 静态代理 代理类在编译期间就生成,但是在生成时将相应的切面织入到代理类中 Cglib 动态代理 代理类在运行时动态生成,底层使用字节码处理框架ASM,来转换字节码并生成新的类 弥补JDK动态代理只能代理接口的不足,cglib可以动态代理类 JDK动态代理 动态代理 代理类在运行时动态生成,源码级别会调用一个Native方法 只能代理接口

关于cglib代理,可以阅读小编的另外一篇博客cglib代理的使用

一、Spring 中使用 AspectJ 1、xml 中开启 aspectJ注解支持

applicationContext.xml

2、声明切面类 @Aspect @Component public class ExecutionAspect { @Before("execution(* wokao666.club.myapp.aspectJ.*.before*(..))") public void doBefore(JoinPoint joinPoint) throws Throwable { System.err.println("这是一个前置通知,在方法调用之前被执行!!!"); } @After("execution(* wokao666.club.myapp.aspectJ.*.after*(..))") public void doAfter(JoinPoint joinPoint) throws Throwable { System.err.println("这是一个后置通知,在方法调用之后被执行!!!"); } @Around("execution(* wokao666.club.myapp.aspectJ.*.around*(..))") public void doAround(ProceedingJoinPoint joinPoint) throws Throwable { System.err.println("这是一个环绕通知,在方法调用前后都会执行!!!"); System.err.println("执行前"); joinPoint.proceed(); System.err.println("执行后"); } }

说明下上面的切入点表达式,execution表示连接点类型,第一个*表示拦截的方法但返回值类型,*表示任意类型返回值;第二部分wokao666.club.myapp.aspectJ.*.before*(..)表示以wokao666.club.myapp.aspectJ包下的任意类的所有以before开头的方法。

3、测试类Main.java public class Main { private static ClassPathXmlApplicationContext ctx = null; public static void main(String[] args) { ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); TestMethod test = (TestMethod) ctx.getBean("bean"); test.before("before"); System.err.println("====================================================="); test.after("after"); System.err.println("====================================================="); test.around("around"); } 4、bean类 @Component("bean") public class TestMethod { public void before(String name) { System.err.println("the param Name is " + name); } public void after(String name) { System.err.println("the param Name is " + name); } public void around(String name) { System.err.println("the param Name is " + name); } }

pom.xml

aspectj aspectjrt 1.5.4 org.aspectj aspectjweaver 1.9.1

执行结果:

这是一个前置通知,在方法调用之前被执行!!! the param Name is before ===================================================== the param Name is after 这是一个后置通知,在方法调用之后被执行!!! ===================================================== 这是一个环绕通知,在方法调用前后都会执行!!! 执行前 the param Name is around 执行后 二、基于自定义注解的拦截实现

有时候我们会使用自定义注解来标识我们的业务方法,下面将讲解AspectJ拦截基于注解的实现,跟生面的差别在于切入点表达式的区别而已。

1、创建一个自定义注解RpcService /** * 远程服务注解,主要用于拦截日志、错误码等方面处理 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(value = { ElementType.METHOD, ElementType.TYPE }) public @interface RpcService { } 2、声明业务方法 @Component("bean") public class TestMethod { @RpcService public void around(String name) { System.err.println("the param Name is " + name); } } 3、声明切面类 @Aspect @Component public class AnnotationAspect { @Around("@annotation(wokao666.club.myapp.annotation.RpcService)") public void doAround(ProceedingJoinPoint joinPoint) throws Throwable { System.err.println("这是一个环绕通知,在方法调用前后都会执行!!!"); System.err.println("执行前"); joinPoint.proceed(); System.err.println("执行后"); } } 4、测试类 public class Main { private static ClassPathXmlApplicationContext ctx = null; public static void main(String[] args) { ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); TestMethod test = (TestMethod) ctx.getBean("bean"); test.around("around"); } } 5、执行结果 这是一个环绕通知,在方法调用前后都会执行!!! 执行前 the param Name is around 执行后

毕业了,怎么感觉有点心浮气躁,稳住稳住!

如果我们想获取被切方法的返回值,那么我们可以使用

MethodSignature si = (MethodSignature) joinPoint.getSignature(); System.err.println(si.getReturnType());


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3