谈谈对Spring的理解之AOP

1. 什么是AOP

在谈到spring的时候,我们总是会听到这2个名词:

  1. IOC:全称叫Inversion of Control,翻译过来叫控制反转
  2. AOP:全称叫Aspect Oriented Programming,翻译过来叫面向切面编程

那么什么是面向切面编程呢?这是一种软件设计思想,一种设计模式,并不指具体的代码,一个良好的AOP设计,可以让我们更好的遵循软件设计的2个重要原则:

  1. SRP原则:Single Responsibility Principle,单一职责原则
  2. DRY原则:Don’t Repeat Yourself,不要重复原则

关于IOC可以参考我的另一篇文章谈谈对Spring的理解之IOC

2. SRP原则所解决的问题

在我们非常熟悉的面对对象过程中,我们会把一个一个的实体,抽象成一个类,同时把一段业务代码逻辑封装成一个方法。比如,我们现在有一个方法pay,很好的封装了付款的逻辑

    // 付款方法
    public void pay() {
        // 很好的封装了付款的代码逻辑
    }

随着系统业务的复杂化,现在要求在付款前,加上一个权限验证的方法。那么这个时候代码就变成了这样

    // 付款方法
    public void pay() {
        // 加一段权限验证的代码逻辑
        
        // 很好的封装了付款的代码逻辑
    }

这个时候,就已经违反了代码的单一职责原则,即一个类一个方法,应该只做一件事情,那么pay方法,就应该只是高内聚付款的代码逻辑即可,而不应该加上权限验证的代码逻辑(注意,这只是站在设计的角度,做讲解用,实际运用中不一定)。那么违反这个原则会带来什么不好的影响呢? 这个例子中是看不出有什么影响的。但是注意,在实际的系统中,可能会有非常多的地方调用pay这个方法,比如突然有一天,来自功能1的地方调用pay方法不需要加权限验证了,而功能2、3、4、5的地方依然还要加上权限验证,这个时候,就体现出违反SRP所带来的后果了。代码变成了这样:

    // 付款方法
    public void pay(boolean isSource1) {
        if (!isSource1) {
            // 不是来着功能1的调用,才需要加上权限验证
            // 加一段权限验证的代码逻辑
        }

        // 很好的封装了付款的代码逻辑
    }

而因为这一个改动,所有调用pay方法的地方,都要去修改,如果系统有上百个地方要调用了?甚至系统中有的功能写的程序员离职了,你还得去看他之前的功能,来判断这一次修改影不影响之前的功能。所以这就是不遵循SRP带来的问题。

3. DRY原则所解决的问题

对于前面的问题,会有人质疑,那权限验证方法不要加在pay方法里,直接在调用的地方加不就好了。这确实保证了pay方法的SRP,但是又违反了DRY的原则。比如系统中有上百个地方调用pay,那么是不是要在每一个调用的地方加上权限验证?而且,这个权限验证的代码是硬编码在代码里,不可以通过配置的方式,来决定这个方法加不加权限验证。
在举个例子,有3个方法,test1、test2、test3,都有自己的业务逻辑:

    public void test1() {
        // test1 的业务
    }
    
    public void test2() {
        // test2 的业务
    }
    
    public void test3() {
        // test3 的业务
    }

这个时候,有一个需求,要在test1、test2、test3方法结束后,加一段日志记录的功能,并且是可以灵活配置的。那么在每个方法结束后,都加上一个日志记录的代码

    public void test1() {
        // test1 的业务

        // 日志记录代码第一行
        // 日志记录代码第二行
        // ....
    }

    public void test2() {
        // test2 的业务

        // 日志记录代码第一行
        // 日志记录代码第二行
        // ....
    }

    public void test3() {
        // test3 的业务

        // 日志记录代码第一行
        // 日志记录代码第二行
        // ....
    }

这里就违反了DRY原则,即代码重复了,如果日志记录的代码改动,那3个调用的地方都要改,会出现漏改或者错改的情况。
其实这里大家都知道,正确的做法是讲日志记录抽象出一个方法log,然后test1、2、3都调用这个方法就好了,这样日志记录的代码改动,只要改log里面的逻辑就好:

    public void test1() {
        // test1 的业务

        // 调用日志记录
        log();
    }

    public void test2() {
        // test2 的业务

        // 调用日志记录
        log();
    }

    public void test3() {
        // test3 的业务

        // 调用日志记录
        log();
    }

    // 通用日志记录
    public void log() {
        // 日志记录代码第一行
        // 日志记录代码第二行
        // ....
    }

确实,这很好的遵循了DRY原则。可是AOP赋予了我们更好的特性,即可以通过配置的方式来动态决定方法的调用

4. AOP的实现原理

spring的AOP是通过动态代理的方式实现的,关于动态代理,可以参考我的另一篇文章动态代理设计模式
spring中我们常见的AOP应用有:

  • 事务处理
  • 日志记录
  • 权限验证
  • 异常处理
  • 性能监控
  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值