Spring 通过注解了解AOP

本文通过一个网站主页Controller的例子,详细介绍了面向切面编程(AOP)的概念及应用。包括如何使用AspectJ注解声明切点、匹配方法、参数及注解等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先抛开那些复杂的的名词,我们来看个简单的例子。假如我们在编写一个网站

网站主页的controller

@Controller
public class IndexController{
    @RequestMapping(path = {"/","/index"} ,method ={RequestMethod.GET})
    @ResponseBody
    public String index() {
        System.out.println("hello");
        return "hello";
    }
}

AOP切面

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect           //用@Aspect注解声明整个类是一个切面
@Component        //一定要将切面注入
public class AOP {

    //用@Before注解声明一个切点,在目标方法调用之前执行
    @Before("execution(* com.myzhihu.controller.IndexController.index(..))")
    public void before(){
        System.out.println("before");
    }

    //用@After注解声明一个切点,在目标方法执行完后执行
    @After("execution(* com.myzhihu.controller.IndexController.index(..))")
    public void After(){
        System.out.println("After");
    }
}

那么我们每次访问localhost:8080/index 时 控制台都会输出
这里写图片描述
这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。


切点的声明

AspectJ注解声明切点有如下通知方法

@Before 在目标方法调用之前执行
@Around 将目标方法封装起来
@After 在目标方法返回或者抛出异常后调用
@AfterThrowing 在目标方法抛出异常后调用
@AfterReturning 在目标方法返回后调用


切点的匹配

切点就是我们想把切面程序切入到哪里去.

我们看到,相同的切点表达式我们重复了两遍,好在我们可以使用@Pointcut来定义可重用的切点

@Aspect
@Component
public class AOP {

    @Pointcut("execution(* com.myzhihu.controller.IndexController.index(..))")
    public void index(){}

    @Before("index()")
    public void before(){
        System.out.println("before");
    }

    @After("index()")
    public void After(){
        System.out.println("After");
    }
}

index()方法并不重要,他是个空的,只是供给@Pointcut依附。

1.execution匹配具体方法
这里写图片描述
execution也支持通配符
你也可以用execution(* com.myzhihu.controller.IndexController.*(..))来表示IndexController类中的任何方法都做切点。
也可以用execution(* com.myzhihu.controller.Controller.(..))来表示用controller包下所有以Controller结尾的类中的所有方法做切点。

2.within来匹配包和类

//&& 代表and  within里代表myzhihu包下所有子包的方法被调用时
@Pointcut("execution(* com.myzhihu.controller.IndexController.index(..)) && within(com.myzhihu.*)")
public void test(){}

3.参数匹配

//匹配任何以index开头并且只有一个int型参数的方法
@Pointcut("execution(* *..index*(int))")
public void argsDemo1(){}

//匹配任何只有一个int型参数的方法
@Pointcut("args(int)")
public void argsDemo2(){}

//匹配任何以index开头并且第一个参数为int型的方法
@Pointcut("execution(* *..index*(int,..))")
public void argsDemo3(){}


//匹配任何第一个参数为int型的方法
@Pointcut("args(int,..)")
public void argsDemo2(){}

4.匹配注解

//匹配方法标注有@RequestMapping的方法(注意,注解只能是方法级别的)
 @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void annotationDemo(){}

//匹配标注有@Controller的类底下的方法(注意,注解必须是类级别)
@Pointcut("@within(org.springframework.stereotype.Controller)")
public void withinDemo(){}

//匹配标注有Controller的类底下的方法,注解的RetentionPolicy必须为RUNTIME
@Pointcut("@target(org.springframework.stereotype.Controller)")
public void targetDemo(){}

//匹配传入的参数类标注有@Component的方法
@Pointcut("@args(org.springframework.stereotype.Component)")
public void argsDemo(){}


小结:

AOP是对面向对象编程的一个强大的补充。通过AspectJ,我们可以把之前分散在应用各处的行为放入可重用的模块中,这有效的减少了代码冗余,让我们的类关注自身的主要功能。
而且可以无侵入的为代码添加功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值