一文搞懂AOP 通俗易懂


前言

提示:这里可以添加本文要记录的大概内容:

Spring有两大核心,AOP和IOC,本文着重讲解AOP。


一、AOP是什么?

AOP是Aspect Oriented Programming,即面向切面编程。
什么是面向切面呢?
要理解AOP的概念,我们先用OOP举例,OOP大家都知道,面向对象编程。比如一个业务组件BookService,它有几个业务方法:

  • createBook:添加新的Book;
  • updateBook:修改Book;
  • deleteBook:删除Book。

对每个业务方法,例如,createBook(),除了业务逻辑,还需要安全检查、日志记录和事务处理,它的代码像这样:

public class BookService {
    public void createBook(Book book) {
        securityCheck();
        Transaction tx = startTransaction();
        try {
            // 核心业务逻辑
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        }
        log("created book: " + book);
    }
}

然后你就会发现增删改的方法都需要做这些判断,很繁琐,解决办法有两种:
一种可行的方式是使用Proxy模式,将某个功能,例如,权限检查,放入Proxy中,但是这种方式的缺点是比较麻烦,必须先抽取接口,然后,针对每个方法实现Proxy。
所以第二种方法AOP应运而生了。
AOP技术看上去比较神秘,但实际上,它本质就是一个动态代理,让我们把一些常用功能如权限检查、日志、事务等,从每个业务方法中剥离出来。

二、使用步骤

1.引入Aspect依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring.version}</version>
</dependency>

2.编写代码

这里我先模拟一个简单的场景,用最简洁的代码教会大家。
假设我们进行了一条数据的更新(update),需要记录日志,如果报错需要抛出异常,这时候我们可以用到前置通知(其实是在插入成功后,后置通知)和异常通知

2.1 使用注解+AOP方式实现切面

首先我们定义一个注解类AdminOnly

@Retention(RetentionPolicy.RUNTIME)  //运行期
@Target(ElementType.METHOD) //作用在方法上
public @interface AdminOnly {
}

然后就可以编写切面类了,

@Aspect
@Component
public class CheckUserAspect {

    //注解方式,方法其实是个空壳
    //此时注解就跟此方法绑定了,后续使用注解的方法都会被带上切面所标识的方法
    @Pointcut("@annotation(com.tao.aop.annotation.AdminOnly)")
    private void checkAdmin(){

    }


    @Before("checkAdmin()") // 前置通知,checkAdmin()跟拦截器进行绑定
    private void Before(){
        System.out.println("前置通知...日志记录");
    }

    @AfterThrowing( value = "checkAdmin()",throwing = "e")  //异常通知 checkAdmin()跟拦截器进行绑定
    private void afterThrowing(Throwable e) {
        System.out.println("报错后通知...");
        System.out.println(e.getMessage());
    }
}

UserService类

@Service
public class UserService {

    @AdminOnly  //注:要想被切面的方法需要加上这个注解
    public void update() {
        System.out.println("进行了update操作...");
    }
}

此时使用测试类,调用UserService中的update方法,你会发现结果是:

前置通知…权限校验
进行了update操作…

已经加上了AOP操作。接下来讲解通过execution来划定范围

2.2 使用execution+AOP方式实现切面

切面类 CheckUserAspect ,看得出,我把service包下的所有类,所有方法都拦截了

@Aspect
@Component
public class CheckUserAspect {

 //表达式方式
    // execution 代表的意思
    /*
    * 第一个 * 号代表返回值为任意类型
    *第二位代表 包名
    *第三位 .* 代表任意类
    *第四位 .*(..) 表示任何方法名的任何参数
    *
    * */
    @Pointcut("execution(* com.tao.aop.service.*.*(..))")
    private void checkAdmin(){
        //此方法是空壳
    }


    @Before("checkAdmin()") // 前置通知,checkAdmin()跟拦截器进行绑定
    private void Before(){
        System.out.println("前置通知...日志记录");
    }

    @AfterThrowing( value = "checkAdmin()",throwing = "e")  //异常通知 checkAdmin()跟拦截器进行绑定
    private void afterThrowing(Throwable e) {
        System.out.println("报错后通知...");
        System.out.println(e.getMessage());
    }
}

UserService1类

@Service
public class UserService1 {


    public void update() throws Exception {

        System.out.println("进行了update操作...");
        throw new  Exception("自造异常");
    }
}

前置通知以及我自己模拟的异常通知都触发了,结果如下:

前置通知…权限校验
进行了update操作…
报错后通知…
自造异常

3. 写在最后

还有一些拦截通知类型,我就不一一举例,感兴趣的同学可以关注公众号,探讨及提问。

@Before:这种拦截器先执行拦截代码,再执行目标代码。如果拦截器抛异常,那么目标代码就不执行了;

@After:这种拦截器先执行目标代码,再执行拦截器代码。无论目标代码是否抛异常,拦截器代码都会执行;

@AfterReturning:和@After不同的是,只有当目标代码正常返回时,才执行拦截器代码;

@AfterThrowing:和@After不同的是,只有当目标代码抛出了异常时,才执行拦截器代码;

@Around:能完全控制目标代码是否执行,并可以在执行前后、抛异常后执行任意拦截代码,可以说是包含了上面所有功能。

总结

总的来说,AOP已经是开发必备或者说面试必问,老生常谈的问题了,如果想要详细源码或者不懂的地方关注公众号,回复AOP实例源码 即可获取全部源码

如果您有Java方面的问题(不局限于此文章的问题),欢迎公众号提出您的问题,我将在第一时间为您解答~

在这里插入图片描述

有惊喜哟~
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring AOP是Spring框架的一个重要组成部分,它是一种面向切面编程的技术。通过预编译方式和运行期动态代理,Spring AOP可以实现对程序功能的统一维护。它主要应用于事务处理、日志管理、权限控制、异常处理等方面。Spring AOPAOP的一种实现方式,它与AspectJ是目前最流行的AOP框架之一。\[1\]\[2\] #### 引用[.reference_title] - *1* [Spring AOP是什么?](https://blog.csdn.net/weixin_45743799/article/details/104803679)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Spring-AOP是什么](https://blog.csdn.net/jj89929665/article/details/130875982)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [普歌-云言团队-Spring的AOP简介](https://blog.csdn.net/qq_45812355/article/details/107673115)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旋律~学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值