简单聊聊AOP

对一个技术的思考,基本上都是从上学时候课本阐述一个新知识的顺序进行的。

第一:什么是 AOP?

第二:为什么要引入 AOP?或者是 AOP 解决了什么问题?

第三:如何简单的实现 AOP?

第四:AOP 对我们写代码时候的思考和帮助是什么?

现在,开始对 AOP 进行阐述,

1 什么是 AOP?

1.1 概念介绍

Spring 的使命是简化 Java 代码开发,aop 作为 Spring 的一个子模块,也不例外。

AOP 是 Aspect Oriented Programming(面向切面编程) 的简称,和 OOP(面向对象编程)一样是一种编程思想,是对 OOP 的一种补充。

如何理解什么是 AOP 呢?以日志为例,在很多管理系统,比如订单系统、推送系统等等都需要把日志记录下来。如果每个业务逻辑里面都写日志的相关代码,那就重复太多了。

干脆把日志的相关逻辑代码,统一封装起来。然后在需要的地方嵌入即可。AOP 也主要就是做嵌入这件事的。看下面这张图。

84f74238-de3b-4dd9-86c3-2cd4e38f2395.png

新增订单编辑订单取消订单推送订单日志事务

AOP 旨在将横切关注点(crosscutting concern)从业务主体逻辑中进行剥离,实现关注点分离,以提高程序的模块化程度(及业务模块只需关注业务逻辑,无需关注日志、安全、事务等通用逻辑)

上面提到了一些名词,比如说,切面、关注点、横切等,下面对这些名词进行解释。

1.2 名词解释

  1. AOP 有自己的一套术语,我们必须了解一下这些行话,才能更好地理解 AOP。为了方便大家理解,下面将用课代表收作业作为例子。

    1.通知 (Advice)

    定义了在收作业前后需要做的事。常见的通知类型有:before、after、after-returning、around 等。
    

    2.连接点 (JoinPoint)

    连接点指程序运行时允许插入切面的一个点,可以是一个函数、一个包路径、一个类、或者抛出的异常。有点类似于可以收作业的时间点。
    

    3.切点(PointCut)

    切点用于定义切面的位置,也就是捕获哪些连接点的调用然后执行"通知"的操作(什么地点)。
    

    4.切面(Aspect)

    切面是切点和通知的聚合,定义了在哪一个切点做什么通知。
    

    5.目标对象( Target )

    指被切面织入的对象。
    

    6.引入(Introduction)

    引入允许我们向现有的类添加新方法或属性。
    

    7.织入(Weaving)

    织入是把切面应用到切点对应的连接点的过程。切面在指定连接点被织入到目标对象中。
    

具体关系使用图形化表示是:
2.png

2 为什么要引入 AOP?

上面是定义,引入 AOP 的原因肯定是可以解决目前开发中存在的某些痛点:

(1)目前的开发当中,相互之间都是模块化开发,使用 AOP 可以有效的实现模块化的思路。

(2)将辅助逻辑(日志、安全、监控等)从业务主体逻辑中进行剥离,同步进行开发。

AOP 是一种思想,这种思想是把一些业务逻辑剥离开,然后按照主业务逻辑进行组合,最后达到想要的功能逻辑。

3 如何简单的实现 AOP?

3.1 AOP 编程思路

本图是一个简单的思路。

3.png

明确需求创建切面类定义切点定义通知思考:要在哪个方法的什么时候做什么事(方法前?方法后? 还是 around ?)即选择哪个连接点进行执行通知在切点附近(before?after?) 做什么操作

下面定义一个日志的简单案例,实现 AOP。使用的是原始的注解方式:

3.2 案例实现 AOP

3.2.1 明确需求

在某个方法上加上@FddLog,就会在执行这个方法的前后,自动输出相应的信息。下面以把大象放进冰箱为例子进行演示:

3.2.2 基本接口和实现
public interface ElephentToRe{
  public void toRe();
}
实现类如下:
public class ElephentToReImpl implements ElephentToRe{
  public void toRe() {
    System.out.println("把大象放冰箱");
  }
}
3.2.3 定义切面和通知
    public class ElephentToReHelper {
        public void beforeElephentToRe() {
            System.out.println("把冰箱门打开");
        }

        public void afterElephentToRe() {
            System.out.println("把冰箱门关上");
        }
    }
配置就好了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
  <!-- 定义通知内容,也就是切入点执行前后需要做的事情 -->
  <bean id="elephentToReHelper" class="com.fdd.bean.ElephentToReHelper"></bean>
  <!-- 定义被代理者 -->
  <bean id="elephentToReImpl" class="com.fdd.bean.ElephentToReImpl"></bean>
  <aop:config>
    <aop:aspect ref="elephentToReHelper">
      <aop:before method="beforeElephentToRe" pointcut="execution(* *.toRe(..))" />
      <aop:after method="afterElephentToRe" pointcut="execution(* *.toRe(..))" />
    </aop:aspect>
  </aop:config>
</beans>
3.2.4 测试看效果
    public class Test {
        public static void main(String[] args) {
            @SuppressWarnings("resource") ApplicationContext appCtx = new FileSystemXmlApplicationContext("application.xml");
            ElephentToRe elephentToReImpl = (ElephentToRe) appCtx.getBean("elephentToReImpl");
            elephentToReImpl.toRe();
        }
    }

上面的这种方法是通过纯粹的 POJO 切面来完成的。实现方式也比较简单。

4 我对 AOP 思想的看法

任何新技术的出现都是为了解决目前开发中存在的某些痛点。对于 aop 来说,其主要是把一些功能代码进行抽象封装,和主业务逻辑代码进行剥离。在需要的地方进行织入即可。

我的看法是

(1)在平时开发代码的时候,完全可以把一些常见的,常用的功能代码进行封装,尽量做到动态配置。不同的功能模块只需要进行织入即可。

(2)定义业务逻辑的模板,比如说如果要解决某一个业务功能,如果页面类似,可以按照基本的框架进行组合,然后使用配置平台进行可控化配置即可。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值